Matterhorn 28-012 · PDF/UA-1 UA1:7.18.5-2

Link annotation with no Contents description

Blocker Checkpoint 28: Annotations WCAG 2.4.4 (A)

Link annotations need /Contents describing where the link goes.

The condition, as the protocol states it. “A link annotation does not include an alternate description in its Contents entry.”

Matterhorn Protocol 1.1, checkpoint 28, index 28-012, section UA1:7.18.5-2. Software can decide this one on its own.

What a screen reader actually does

The links list shows entries with no description, and a bare URL is read character by character.

What is in the file

The description lives on the annotation:

19 0 obj
<< /Type /Annot
   /Subtype /Link
   /Rect [ 72 640 300 660 ]
   /F 4
   /Contents (Privacy notice, opens example.gov)     % ← this
   /A << /S /URI /URI (https://example.gov/privacy) >>
   /StructParent 3
>>
endobj

Condition 28-012 is /Contents being absent or empty on a link annotation that is otherwise in scope — not hidden, not outside the crop box.

It is a separate condition from 28-011, which is about the link having a <Link> structure element at all. A link can be perfectly placed in the structure tree and still have no description, and vice versa. Both are needed.

What the user gets

Screen readers give users a links list — Insert + F7 in NVDA, VO + U in VoiceOver — which is how most people navigate a document’s links. That list shows the link text, and where the text is unhelpful the reader falls back to whatever else it can find.

With no description and text reading “click here”, the list is a column of identical entries. With a bare URL as the text, the entry is read character by character:

h t t p s colon slash slash e x a m p l e dot g o v slash p r i v a c y

Thirty seconds to hear one link. On a page with twelve references, the links list becomes the slowest way to navigate the document rather than the fastest.

How to fix it free, in Acrobat Pro

Acrobat has no field labelled “link description”, which is why this gets missed. It is on the structure element:

  1. Open the Tags panel.
  2. Find the <Link> element containing the link. If there is no <Link> element, fix 28-011 first: select the tag containing the link text, then Options → Find → Unmarked Links → Find → Tag Element.
  3. Right-click the <Link>Properties.
  4. Type into Alternate Text.

That writes an /Alt on the structure element, which PDF/UA-1 accepts in place of /Contents on the annotation. Both satisfy the condition; /Contents is what more readers look at first, and it is what Taggart writes.

Upstream: Word and InDesign both export real hyperlinks as tagged <Link> elements, and Word carries a ScreenTip (Insert → Link → ScreenTip) into the export as the description. Setting ScreenTips in the source is the only version of this job that scales.

The links list removes all context, so the text has to carry its own. Three rules that hold up:

Never “click here”, “read more”, “here” or a bare URL.

Front-load the distinguishing word. Privacy notice (PDF, 240 KB) beats Download our privacy notice as a PDF — the first two words already identify it.

Two links with the same text must go to the same place. Otherwise the list contains two identical entries with different destinations, and the user has no way to choose.

Where Taggart differs

Taggart reports each link with its page and object id, so you can find it:

A link annotation on page 3 has no /Contents entry describing where the link goes.

The description is a human decision and Taggart will not invent one. What it offers is a starting point: with useUriAsDescription set, it writes the target URI as the description and marks every one it filled that way in the change log —

page 3: set link /Contents to ‘https://example.gov/privacy’ (derived from the target URI — review the wording)

— so it never reads as a wording somebody chose. A bare URI announced is poor; a link announced with no destination at all is worse, and the log makes clear which you have.

How Taggart handles it

Taggart detects this condition automatically. It is reported as a blocker, with the page, the structure path and the object id of every occurrence.

The fix is Build link structure elements. It changes what the document means, so Taggart proposes it and waits for your approval rather than applying it unattended.

Whatever Taggart changes, the page still looks identical. Fixes edit the PDF object model, not the content streams, and every remediation is re-rendered and compared against the original at structural similarity ≥ 0.999 before you get the file back. A tool that quietly reflows your document is worse than no tool.

Frequently asked questions

Isn't the link text enough?

Often, yes — and where the visible text is descriptive, /Contents can repeat it. The problem is that a great many links read 'click here', 'read more' or the raw URL, and those tell a user nothing when the links list strips away the surrounding sentence.

What should /Contents say?

Where the link goes, in the fewest words that distinguish it. 'Privacy notice, opens example.gov' beats both 'click here' and the full URL. If the visible text is already good, matching it is fine.

Is this the same as WCAG 2.4.4?

It is how a PDF satisfies it. WCAG 2.4.4 Link Purpose (In Context) is Level A and asks that a link's purpose be determinable. In PDF that means the Link structure element carries the text and the annotation carries a description.

What about a URL that is meant to be read aloud — a citation?

Then the URL is the content and it belongs in the visible text. /Contents can still describe it: 'DOI link to the 2026 survey'. The reader gets the description first and the URL only if they want it.

Where this sits in the standards

Standards this condition maps to
StandardReference
Matterhorn Protocol 1.1 Checkpoint 28 (Annotations), index 28-012
PDF/UA-1 (ISO 14289-1) Clause 7.18.5-2
WCAG 2.1 2.4.4 Link Purpose (In Context) — Level A
EN 301 549 / Section 508 / ADA Title II All three point at WCAG 2.1 Level AA for non-web documents, so a Level A or AA criterion here is in scope for each of them.

Other conditions in checkpoint 28

Checkpoint 28 covers annotations. These are its other failure conditions; the ones without a link are in the rule set but do not have a written page yet.

Check your own file. Taggart’s validator is free and unlimited — every machine-checkable Matterhorn condition, no page cap, no watermark, no account needed.

Check a PDF free

Verified against a real document on . Last updated .