RatedWithAI

RatedWithAI

Accessibility scanner

What do your links say when the page is taken away?

Enter your domain. We read the HTML your server sends and rebuild the list of link names a screen reader navigates by — every link with nothing to announce it, every name used for more than one destination, every “read more” that only works because of the sentence above it, each one under the criterion it actually sits beneath.

Free, instant, no signup and no card. Nothing is stored.

Free, instant, no signup and no card. We read the HTML your server sends for that one page and rebuild the list of link names a screen reader navigates by. Nothing is stored.

The list is the thing you cannot see

Screen readers do not make people read a page from the top. They build a list of every link on it and let the user jump straight to the one they want, and for a lot of people that list is the primary way they move around a site. The list holds the links' accessible names and nothing else — not the headline above them, not the card they sit in, not the table row, not the column header.

Which means a page that reads perfectly with your eyes can be unusable in that list, and you will never find out by looking at it. Eleven “Read more” links under eleven headlines is a normal blog index and an unreadable list. Four “Edit” links in four invoice rows is a normal table and four identical rows out of context. A footer with six social icons and no labels is six rows that read as raw URLs, one character at a time.

This is the same class of defect as a broken heading outline: no visual symptom, so it survives every design review the page ever gets, and it is repeated by a navigation template across every page that template renders. The panel above shows you the list, because the list is the argument.

What this checker refuses to call a failure

Almost every link checker on the web reports “click here” as a WCAG violation. It is not one, and the distinction is worth understanding before you take a report to a developer.

SC 2.4.4 Link Purpose (In Context), level A — the one in nearly every contract and every settlement agreement — is satisfied when the purpose can be determined from the link text or from the link text together with its programmatically determined context. The sentence, the list item, the paragraph and the table cell all count. A “read more” under a headline conforms.

SC 2.4.9 Link Purpose (Link Only) is the criterion that asks the link text to stand alone, and it is level AAA — a tier essentially no organisation is measured against. So a violation count built on 2.4.9 is a count of things that are not violations, and the number it produces is designed to be alarming rather than true.

Three things on this page are called failures: a link with no accessible name at all, an image-only link whose image has no alt attribute, and a visible label that the accessible name does not contain. Each is level A, each names its criterion, and each one is a link a real person genuinely cannot announce or operate. Everything else is in a review band with the argument attached.

What the checker looks for

Three failures, then the review items — real problems that WCAG does not forbid at level A or AA, reported separately and never counted as violations.

Link with no accessible nameFailureWCAG 2.1 SC 2.4.4 Link Purpose (In Context) / SC 4.1.2 Name, Role, Value (Level A)
This element is a link — it has an href, it takes keyboard focus, and it appears in the list a screen-reader user navigates links by — and there is nothing to announce it with. No text, no aria-label, no aria-labelledby, no nested image with alt text, no svg title. A screen reader reads out the destination URL instead, one character at a time, or the word "link" and nothing else. Almost every one of these is an icon link: a social-media glyph, a close X, a chevron in a carousel, or an <a> wrapped around a background image.
The fix: Give the link words. aria-label="Read our privacy policy" on the anchor is the one-line fix for an icon link; alt text on the image inside it works just as well when the image is the label. If the link genuinely goes nowhere, it should not be an anchor with an href.
Image-only link whose image has no alt attributeFailureWCAG 2.1 SC 1.1.1 Non-text Content / SC 2.4.4 Link Purpose (Level A)
The only thing inside this link is an image, and that image carries no alt attribute at all. The image is doing the labelling and has nothing to label with, so the link arrives in the rotor as its own URL. This is the failure that hits logo links and product-grid thumbnails hardest, and it is two criteria at once: the image fails 1.1.1 and the link it labels fails 2.4.4.
The fix: Put the link's destination in the image's alt text — alt="Acme home" on a logo, alt="Blue running shoe, £79" on a product thumbnail. Describe where the link goes, not what the picture looks like. alt="" is correct for a decorative image but never for the only thing inside a link.
Visible words missing from the link's accessible nameFailureWCAG 2.1 SC 2.5.3 Label in Name (Level A)
The link shows one thing on screen and tells software another: an aria-label has replaced the visible text rather than added to it, and the visible words are not inside the name. Anyone driving the page by voice says what they can see — "click Get started" — and nothing happens, because the name the browser matches against does not contain those words. Speech users are the obvious casualty; so is any screen-reader user who can also see the screen, who now hears a label that disagrees with the link they are pointing at.
The fix: Keep the visible words at the start of the accessible name and extend from there: aria-label="Get started with the free plan" over visible text "Get started" passes. Better still, delete the aria-label and let the visible text be the name — an override that has to stay in sync with copy will eventually not be.
One name, several destinationsReviewWCAG 2.1 SC 2.4.4 Link Purpose (In Context) (Level A)
Two or more links on this page share an accessible name and go to different places. In the page this is usually fine and conforming — the row, the card or the paragraph each one sits in tells you which is which, and that context is exactly what SC 2.4.4 at level A permits. Out of the page it is not fine, and out of the page is where link navigation happens: the rotor list shows the names with none of the context, so the user gets the same row repeated and has to open each one to find out which was which. This is the single most useful thing this checker reports, and it is the one no amount of looking at your own page will show you.
The fix: Make the names distinct where they are cheap to change — a table of "Edit" links becomes "Edit invoice 1042". Where the visible text has to stay short, extend the accessible name instead and keep the visible words inside it: visible "Edit", aria-label="Edit invoice 1042".
Name that carries no purpose on its ownReviewWCAG 2.1 SC 2.4.9 Link Purpose (Link Only) — Level AAA, not A or AA
"Read more", "click here", "learn more", "details". Read the severity here carefully, because most checkers get it wrong: this is NOT a level A or AA failure. SC 2.4.4 at level A explicitly allows the surrounding sentence, list item or table cell to supply the purpose, so a "read more" underneath a headline conforms. Only SC 2.4.9 at level AAA asks the link text to stand alone, and almost nobody is contractually measured on AAA. What makes it worth fixing anyway is the links list: it strips the context that 2.4.4 relies on, so twelve "read more" links arrive as twelve identical rows with no way to tell them apart.
The fix: Move the words that are already next to the link into it. "Read more" under a headline becomes "Read: why overlays don't fix lawsuits" — or keep the short visible text and extend the accessible name with aria-label, which is the one case where an override earns its keep, as long as the visible words stay inside it.
Hidden from assistive technology but still focusableReviewWCAG 2.1 SC 4.1.2 Name, Role, Value (Level A)
aria-hidden="true" on a link that still takes keyboard focus. This is the worst of both states: the link is removed from the accessibility tree, so a screen reader announces nothing for it, but tabbing through the page still lands on it. The user's focus moves somewhere the software cannot describe — a silent stop with no name, no role and no way to know what pressing Enter would do. It is usually a collapsed menu or an off-screen carousel slide that was hidden from software but never taken out of the tab order.
The fix: Hide it from everyone or from nobody. If the link is genuinely inactive, add tabindex="-1" alongside the aria-hidden, or remove it from the DOM; if it is active, drop the aria-hidden.
Named only by its title attributeReviewWCAG 2.1 SC 2.4.4 Link Purpose (In Context) (Level A)
The link has no text and no aria-label; the only thing standing between it and having no name at all is the title attribute. Title text is the weakest naming method there is — it renders as a tooltip on hover, so it does not exist for touch or keyboard users, and while most screen readers will fall back to it, that fallback is a preference some users switch off. It counts as a name in the accessibility tree, so this is not called a failure, but it is one browser setting away from being one.
The fix: Move the same words into aria-label on the anchor, or into the alt text of the image inside it. Both are announced unconditionally. Keep the title as well if you want the tooltip; just stop relying on it.
Bare URL used as the link textReview
The link's name is the address itself. Most screen readers read a long URL character by character — slashes, hyphens, percent-encoding and all — which takes far longer than the sentence it replaced and conveys less. There is no criterion that forbids it; it is simply a worse name than the page's own title, which you already have.
The fix: Use the destination's title as the link text and keep the URL in the href. Where the literal address matters (a citation, a docs reference someone will copy), a short display form like example.com/pricing reads acceptably.
Opens a new tab without saying soReviewWCAG 2.1 SC 3.2.5 Change on Request — Level AAA, not A or AA
target="_blank" with nothing in the accessible name or the title attribute to warn about it. Sighted mouse users notice the new tab; a screen-reader user hears nothing change, and the Back button they reach for next does not work because there is no history in the new tab to go back through. This is level AAA — it is not a conformance failure at AA — and it is one of the cheapest confusions on the web to remove.
The fix: Say it in the name: aria-label="Read the WCAG 2.1 spec (opens in a new tab)", or append a visually-hidden span carrying "(opens in a new tab)" so the words are in the name and the layout is untouched. An icon alone does not do it unless the icon has alt text or a title.
Paragraph-length link textReview
The anchor wraps a whole sentence or more. There is no length limit in WCAG, so this is advisory, but a name over about a hundred characters is read out in full every time the link is announced and in full again in the links list, and it is usually a symptom rather than a choice — an <a> wrapped around an entire card so that the headline, the standfirst, the date and the author all became one name.
The fix: Put the anchor around the card's headline and make the rest of the card clickable with a CSS overlay or a click handler on the container. The name becomes the headline, the whole card stays clickable, and nothing about the layout changes.

How to write a link name, in one rule

Make the name work with the page removed. That is the whole rule, and it is cheaper to follow than to audit — every fix below is a copy change or one attribute.

  1. Move the words that are already next to the link into it. “Read more” under a headline becomes “Read: why overlays don't fix lawsuits”. The information exists; it is just in the wrong element.
  2. Where the visible text has to stay short, extend the name instead of replacing it. Visible “Edit”, aria-label="Edit invoice 1042" — the visible words stay inside the name, so voice control still works and SC 2.5.3 is satisfied. Replacing them is the failure this page reports.
  3. Every icon link gets words. aria-label on the anchor, or alt text on the image inside it. Describe the destination, not the picture: a logo is alt="Acme home", not alt="logo".
  4. Wrap the headline, not the card. An anchor around a whole card makes the headline, the standfirst, the date and the author into one name that gets read out in full every time. Anchor the headline and make the card clickable with a CSS overlay.
  5. Say it when a link opens a new tab. A visually-hidden span carrying “(opens in a new tab)” puts the words in the name and changes nothing on screen.

Common questions

Is "click here" actually a WCAG failure?
No, and a tool that tells you it is has told you something false. SC 2.4.4 Link Purpose (In Context) is the level A criterion, and it says the purpose can be determined from the link text OR from the link text together with its programmatically determined context — the sentence, the list item, the paragraph, the table cell it sits in. A "read more" directly under a headline conforms. The criterion that asks link text to stand alone by itself is SC 2.4.9 Link Purpose (Link Only), and that is level AAA, which almost nobody is contractually measured against. This checker puts generic text in a review band and tells you the argument instead of inventing a verdict. Three things here are called failures, and each one is a link somebody genuinely cannot operate.
Then why fix generic link text at all?
Because of the list. Screen readers let users pull up every link on the page as a list and jump straight to the one they want, and that list contains the accessible names and nothing else — the context that SC 2.4.4 relies on is exactly what link navigation removes. So eleven "Read more" links that are perfectly conforming in the page arrive as eleven identical rows, and the only way to tell them apart is to leave the list and go read the page, which is what the list existed to avoid. That is a usability cost you pay on every visit, not a compliance risk, and it is why the panel on this page shows you the list rather than just a count.
What does the checker actually read?
One URL, once. It fetches the page you enter, takes the HTML your server returns, and walks every <a> element that has an href, in document order. For each one it works out the accessible name the way a browser does — aria-labelledby first, then aria-label, then the link's own content including any image alt text and svg title, then the title attribute as a last resort — and then asks whether that name can be operated, whether it means anything alone, and whether another link on the page uses the same name for a different destination. It does not render the page, run your JavaScript or crawl beyond the address you typed; all three of those are the full scan, which is a different tool on this site and also free.
My icon links have aria-labels. Will they be reported as empty?
No. An aria-label, an aria-labelledby pointing at real text elsewhere on the page, alt text on the image inside the link, an svg <title>, or a visually-hidden span all count as names, because all of them are announced. That is deliberate: the expensive error for a tool like this is telling a stranger their correctly-labelled icon links are broken. The one thing to watch is the opposite case — an aria-label on a link that also has visible words, where the label does not contain those words. That one IS a level A failure, under SC 2.5.3 Label in Name, and it is reported as one.
Why is an aria-label that replaces the visible text a failure?
Because of voice control. Someone driving the browser by speech says the words they can see — "click Get started" — and the browser matches what they said against the link's accessible name. If the name is "Create your free account" and the visible words are "Get started", the match fails and nothing happens, with no indication why. SC 2.5.3 at level A is the criterion: where a component has a visible text label, the accessible name has to contain that text. Extending is fine and often good: visible "Get started", aria-label "Get started with the free plan" passes. Replacing is the failure.
It says I have unnamed links, but every link on my page has text.
Look for the icons. Almost every unnamed link on a real site is an icon link — a social media glyph in the footer, a chevron in a carousel, a close X on a banner, a logo in the header wrapped around an image with no alt attribute. There is no text inside them, so there is nothing to announce, and on screen they look completely fine. The other common source is an <a> wrapped around a background image or an empty div for a hero banner. The findings list on this page names each one with its href, which is usually enough to find it in your template.
It found no links, but my navigation clearly works. What happened?
Two possibilities, and both are worth knowing. The first is client-side rendering: if the nav is built by React, Vue or a widget after the document arrives, the links are not in the HTML your server sent and this reader cannot see them — the same limitation as the heading, form label and alt text checkers on this site, and the same honest answer. The free scan renders each page in a real browser first, so it sees what your visitors see. The second is worse: the "links" may be clickable divs with onClick handlers. Those take no keyboard focus, carry no link role, appear in no links list, and cannot be reached at all without a mouse.
Does opening a new tab fail anything?
Not at level A or AA. SC 3.2.5 Change on Request is level AAA, and the usual reading is that an unannounced new tab is a change of context the user did not request. What is certain is what happens next: a screen-reader user who does not know a new tab opened reaches for Back, and Back does nothing, because the new tab has no history. It is one of the cheapest confusions on the web to remove — a visually-hidden "(opens in a new tab)" inside the anchor puts the words in the name and changes nothing about the layout.
Does this store my domain?
No. The check is a single HTTP GET of the page you name, run inside the request and discarded when it answers. There is no account, no email field and no row written anywhere. If you go on to run the free scan, that one does keep a report so you can come back to it, which is the whole point of a report.

Keep reading