Image alt text: how to write it, and how to check it

Short answer

Alt text is the alt attribute on an image: <img src="…" alt="Dalmatian puppy playing fetch">. Screen readers read it out, browsers show it when the image fails to load, and Google uses it to understand what the image shows. Every <img> should have an alt attribute. Describe images that carry meaning in a short phrase, and give purely decorative images an empty one: alt="".

Why alt text matters for accessibility and SEO

  • People who can't see the image. Screen readers read the alt text in its place. With no alt attribute at all, some read out the file name instead, such as "IMG underscore 4 0 2 3 dot jpg", and others just say "unlabelled image".
  • Search (alt text SEO). Google says it uses alt text, along with computer vision and the content of the page, to understand what an image is about. Good alt text helps the image show up in Google Images.
  • Linked images. When an image is a link, Google uses its alt text as the link's anchor text, so if a linked logo or icon has an empty alt and no other text, the link has no description at all.
  • Broken images. Browsers show the alt text when the image can't load.

Google doesn't index images set with CSS background-image. If an image matters for search, use an <img> element with alt text.

Which images need it

Not every image needs a description, but every image needs the attribute. Use the image's job to decide:

The image is…Alt textExample
Informative: a product photo, a simple chart, any image that adds meaningA short description of what it showsalt="Navy wool coat with a hood, front view"
Functional: the only thing inside a link or buttonWhat clicking it does, or where it goesalt="Example Ltd home page" on the logo link
Text in an imageThe text it shows, unless that text is next to it anywayalt="20% off all coats this weekend"
Decorative: a divider, a background flourish, an icon next to its labelEmpty, so screen readers skip italt=""
Already described by the text beside itEmpty, to avoid reading it twicealt=""
Complex: a detailed chart or diagramA short summary, with the detail in the page textalt="Sales by month, rising from March to August"

This follows the W3C's alt decision tree. alt="" and no alt are not the same thing: an empty alt says "skip this", a missing one leaves screen readers guessing.

How to write it

<img src="dog.jpg"> Missing. Screen readers may read the file name; Google gets no description.
alt="IMG_4023.jpg" A file name. Usually a CMS filling the field automatically.
alt="dog puppy dogs puppies cheap dog" Stuffed. Google advises against filling alt text with keywords.
alt="puppy" Better. Accurate, but says little.
alt="Dalmatian puppy playing fetch" Good. Specific, short and true to the image.
  • Describe what matters in context. The same photo of a coat needs "navy wool coat, front view" on a product page and maybe "model in the autumn collection" on a campaign page.
  • Keep it short. A phrase or one sentence. Long descriptions belong in the page text.
  • Skip "image of" or "picture of". Screen readers already say it's an image.
  • Use keywords only where they're true. If the photo is of a navy wool coat, say so. Don't add terms the image doesn't show.

How to check by hand

1Check every image on the page 30 seconds

Open DevTools (F12), go to the Console and paste:

// Lists images with no alt, an empty alt, or alt text that looks like a file name,
// and outlines them (red: fix it, orange: fine if decorative). Reload the page to clear the outlines.
const fileLike = a => /^\S+\.(jpe?g|png|gif|webp|avif|svg|heic|bmp|tiff?)(\?\S*)?$/i.test(a)
  || /^(img|image|photo|picture|pic|dsc|pxl|untitled)([-_ ]?\d+)*$/i.test(a)
  || /^screen ?shot[-_ ]?\d/i.test(a);
const named = el => [el.innerText, el.getAttribute('aria-label'), el.getAttribute('title'),
  ...(el.getAttribute('aria-labelledby') || '').split(/\s+/).map(id => id && document.getElementById(id)?.textContent),
  ...[...el.querySelectorAll('img')].map(i => i.getAttribute('alt') || i.getAttribute('aria-label'))]
  .some(v => v && v.trim());
const rows = [...document.images].map(img => {
  const alt = img.getAttribute('alt');
  const link = img.closest('a[href], button');
  const src = img.currentSrc || img.src || img.getAttribute('data-src') || '';
  const result = alt === null ? 'NO alt attribute'
    : !alt.trim() ? (link && !named(link) ? 'EMPTY alt, and nothing else names the link' : 'empty: fine if decorative')
    : fileLike(alt.trim()) ? 'looks like a file name or placeholder'
    : 'ok';
  if (result !== 'ok') img.style.outline = '3px solid ' + (result.startsWith('empty:') ? 'orange' : 'red');
  return {
    image: src.startsWith('data:') ? '(data: URI)' : src ? src.replace(/^https?:\/\/[^/]+/, '').slice(-60) : '(no src yet)',
    alt: alt === null ? '(none)' : alt.slice(0, 60),
    result,
  };
});
console.table(rows.filter(r => r.result !== 'ok'));
console.log(rows.length + ' images checked (images inside shadow DOM and SVG <image> are not included)');

It lists images with no alt attribute, an empty one, or alt text that looks like a file name, and outlines them on the page: red for ones to fix, orange for empty alt text, which is fine if the image is decorative.

A script can't tell whether an image is decorative or whether its alt text is accurate. Use the list to find images to look at, then judge each one yourself. Reload the page to remove the outlines. Images inside shadow DOM and SVG <image> elements aren't checked.

2Inspect an image 30 seconds

Right-click an image and choose Inspect. The <img> tag is highlighted in DevTools, with its alt attribute if it has one. Open the Accessibility tab next to Styles (it may be behind the » button). Under Computed Properties, Name is the label Chrome gives screen readers. If an image that matters has an empty Name, it needs alt text.

3Listen to it 5 minutes

Turn on your computer's screen reader (Narrator: Ctrl+Windows+Enter; VoiceOver: ⌘+F5) and move through the page. You'll hear which images are described, which are skipped, and which are read as a file name or "unlabelled image".

How crawlers report this

If a crawl sent you here, these are the labels to look for. Our guide to Screaming Frog and Sitebulb issues covers other common ones.

Screaming FrogSitebulbWhat it means
Links: Internal Outlinks With No Anchor TextHas an internal link with no anchor textA link has no text to say where it goes.
Images: Missing Alt TextImages with missing alt textAn image has no text alternative.

Doing this on every page?

SEOSnip checks alt text for you

Open the extension on any page and it checks every image. You get:

  • Every image with no alt attribute, with its address and where it sits on the page. Images with alt="" pass, because that's correct for decorative ones
  • Links with no readable text, where an image with alt text counts as text
  • A ticket listing the images (the first 10, with the total), and a "Check if fixed" button that re-runs the check