What does your email sound like with the images off?
Paste an HTML email, or its “view in browser” link. We read the alt text, the links, the layout tables, the language and every inline colour pair, and name each failure by the WCAG criterion it breaks — with the element in your template it comes from.
Free, instant, no signup and no card. Nothing is stored.
Free, instant, no signup and no card. We read the markup once, inside the request, and keep nothing — not the HTML, not the link.
Why an email fails differently from a web page
An HTML email is built for Outlook's 2007-era Word renderer, so its layout is nested tables, its styles are inline and its headline is often a picture. Each of those choices has an accessibility cost a website does not carry.
Images are off by default in a large share of inboxes, so the alt text is not a fallback for screen reader users only — for those opens it is the email. A banner whose offer lives in the pixels, with no alt, arrives as an empty box.
Every layout table talks. Without role="presentation", a reader can announce each nested table's rows and columns before the first sentence. Three levels of nesting is three announcements of furniture.
Webmail throws away your <html>. Gmail and Outlook.com render your message inside their own page, so a language declared only on the root element is gone — and the screen reader guesses the voice.
The pixel is an image too. The open-tracking pixel with no alt="" is read out as its file name or URL. It is the easiest failure in email to miss, because nobody ever sees it.
What this checker refuses to call a failure
A checker that cries wolf on every campaign is worse than none. So a contrast pair is only compared when both colours are written in the markup and readable — text over a background image, a translucent colour, or an unstyled link that takes each client's own link colour is skipped and counted as skipped. Large text is held to 3:1, not 4.5:1. Text hidden with display:none — your preheader — is not measured, and Outlook-only conditional copies are not counted twice. A table with header cells is a data table and is left alone. And font size is reported for you to decide, never counted as a violation: WCAG sets no minimum.
What the checker looks for
- Linked image with no text — the button has no nameFailureSC 2.4.4 Link Purpose / SC 4.1.2 Name, Role, Value (A)
- A link whose only content is an image with missing or empty alt. That is how most image buttons, logos and social icons are built, and a screen reader announces it as "link" followed by the URL — or just "link". The call to action is unreadable.
- The fix: Put the action in the image's alt — alt="Shop the sale" on the button, alt="Acme home" on the logo, alt="Instagram" on the icon. Better still, build the main button as a live-text (bulletproof) button.
- Image with no alt attributeFailureSC 1.1.1 Non-text Content (A)
- With no alt attribute at all, a screen reader announces the image's file name or URL, and an email client with images blocked shows an empty box. In email this is not an edge case: images are off by default in a large share of opens, so the alt text is the message.
- The fix: Add alt to every <img>. Say what the image says — for a banner with words on it, the words. For a purely decorative image, alt="" (empty, but present).
- Tracking pixel or spacer with no altFailureSC 1.1.1 Non-text Content (A)
- The open-tracking pixel and spacer GIFs are images too. Without alt="" a screen reader reads out their file name or tracking URL — usually a string of random characters — before or after your message.
- The fix: Give every pixel and spacer alt="" (and ideally role="presentation"). Most ESPs let you edit the template; if yours injects the pixel, ask them — it is a one-attribute change.
- Link with no text at allFailureSC 2.4.4 Link Purpose (A)
- A link with no text, no image and no aria-label. A screen reader still stops on it and announces only "link". Usually an empty anchor left behind by a template block.
- The fix: Delete the empty anchor, or give it text.
- Text below the 4.5:1 contrast minimumFailureSC 1.4.3 Contrast (Minimum) (AA)
- Text whose inline colour and background, both read from the source, do not reach 4.5:1 (3:1 for large text). Email puts colours inline, so these pairs are declared, not guessed. Light-grey footer text and white-on-brand-colour buttons are the usual offenders.
- The fix: Darken the text or the background until the pair clears 4.5:1 — the colour contrast checker gives the nearest passing shade.
- No language declared anywhereFailureSC 3.1.1 Language of Page (A)
- Nothing in the email says what language it is in, so a screen reader reads it in whatever voice its user's device defaults to. A Spanish newsletter on an English-configured reader is spoken with English pronunciation.
- The fix: Add lang to the <html> element AND to the outermost wrapper (<div lang="en"> or <table lang="en"> around the whole email), because Gmail and Outlook.com strip <html>.
- Layout table without role="presentation"ReviewSC 1.3.1 Info and Relationships (A)
- Email layout is built from tables. Without role="presentation", screen readers in several clients announce each one as a data table — "table, 2 columns, 4 rows" — at every level of nesting, before a word of your message. It is noise rather than lost content, so it is reported as review, but it is the most common email-specific defect there is.
- The fix: Add role="presentation" to every <table> used for layout. Leave it off genuine data tables — a receipt line-item table with <th> headers should stay a table.
- Language declared only on <html>ReviewSC 3.1.1 Language of Page (A)
- The declaration is correct, and it will be read in clients that keep the full document, such as Apple Mail. Gmail and Outlook.com remove the <html> element when they render a message, so in those inboxes the email has no language.
- The fix: Repeat the lang on your outermost wrapper element: <div lang="en" style="…">.
- Almost all of this email is imagesReviewSC 1.1.1 Non-text Content (A) / SC 1.4.5 Images of Text (AA)
- Fewer than 25 words of live text alongside images. With images blocked — the default in many clients — and for every screen reader user, the message is whatever the alt text says. Images of text also cannot be resized, reflowed or restyled for dark mode.
- The fix: Move the headline, the offer and the call to action into live HTML text; keep images for pictures.
- Link text that means nothing out of contextReviewSC 2.4.4 Link Purpose (In Context) (A)
- "Click here", "read more", "learn more". Screen reader users often pull up a list of links; a list of five "click here"s tells them nothing. The surrounding sentence can make it pass, which is why this is review rather than failure.
- The fix: Make the link say where it goes: "Read the October menu", not "Click here".
- Alt text that is a file name or a placeholderReviewSC 1.1.1 Non-text Content (A)
- Alt present but saying nothing: "image", "banner", "hero_v2_final.png". It satisfies an automated check and still tells an images-off reader nothing.
- The fix: Replace it with what the image communicates, or alt="" if it communicates nothing.
- No headings in a long emailReviewSC 1.3.1 Info and Relationships / SC 2.4.6 Headings and Labels
- Screen reader users skim by jumping from heading to heading. An email whose section titles are styled table cells has nothing to jump to, so it has to be heard top to bottom.
- The fix: Mark section titles up as <h1>/<h2> with inline styles (margin:0 keeps the layout identical).
- Body text below 14pxVerify
- Not a WCAG failure — WCAG sets no minimum font size — but most email accessibility guidance asks for 14px or more for body copy, and iOS Mail enlarges anything under 13px on its own, which can break a layout. Reported so you can decide, never counted as a violation.
- The fix: Set body copy to 14–16px inline.
Common questions
- Do emails have to meet WCAG?
- WCAG is written for web content, and an HTML email is web content rendered by a mail client, so its success criteria apply directly — alt text (1.1.1), link purpose (2.4.4), language (3.1.1) and contrast (1.4.3) all mean the same thing in an inbox. Whether you are legally required to meet them depends on who you are: US federal agencies under Section 508 are, public bodies covered by the 2024 ADA Title II rule are for the content they send, and the European Accessibility Act covers e-commerce services sold into the EU, which can reach the messages those services send. Private US businesses are sued over websites far more than emails, which is why the result hands off to a scan of the site the email links to.
- How do I get my email's HTML?
- Every major ESP exposes it. In Mailchimp, open the campaign and use the code view, or export the template as HTML. In Klaviyo, open the template editor's HTML view. In HubSpot, Brevo, Campaign Monitor and most others there is a view source or export option. Or send yourself a test, and in Gmail choose Show original; in Apple Mail, View → Message → Raw Source. Alternatively paste the campaign's "view in browser" link and we fetch the hosted copy.
- Why does role="presentation" matter on email tables?
- Almost every HTML email is laid out with nested tables, because Outlook's Word rendering engine cannot do CSS layout. A table with no role is exposed to assistive technology as a data table, so in several screen reader and client combinations each one is announced — "table, 2 columns, 4 rows" — and every nested level adds another announcement before a word of the message is read. role="presentation" tells the reader the table is layout only. Leave it off genuine data tables, such as an order summary with header cells.
- Does the tracking pixel really need alt text?
- It needs an empty alt, alt="". The pixel is an <img> like any other, and with no alt attribute a screen reader falls back to reading the file name or the source URL — often a long tracking string — at the very top or bottom of the message. An empty alt marks it as decorative and it is skipped. If your ESP injects the pixel itself, it is usually already handled; this checker tells you whether it is.
- Why isn't my lang attribute enough?
- Because webmail clients do not keep your <html> element. Gmail and Outlook.com embed your message inside their own page and strip the document wrapper, so a lang declared there never reaches the screen reader. Apple Mail and some desktop clients keep it. The robust pattern is to declare it twice: on <html>, and on the outermost <div> or <table> that wraps the whole email.
- How does the checker measure contrast without rendering the email?
- Emails put their styles inline, because most clients strip <style> blocks, so the text colour and background of each block are usually written right there in the markup. The checker walks up from each piece of text to the nearest declared colour and the nearest declared background (inline background-color, background or the bgcolor attribute) and computes the WCAG ratio — 4.5:1 for normal text, 3:1 for text at 24px or 18.66px bold. It does not guess: a background image, a translucent colour or a value it cannot parse means that pair is skipped and counted as skipped. Unstyled links are not compared, because each client applies its own link colour. Dark mode is not modelled.
- What doesn't it check?
- Anything that needs the email rendered in a real client: how dark mode inverts your colours, reading order in Outlook's renderer, whether animated GIFs flash more than three times a second, and whether your alt text is accurate rather than merely present. It reads inline styles only — <style> blocks are counted and reported, not applied. For those, test in the clients your list uses.
- Does this store my email?
- No. The HTML is read once inside the request and discarded when it answers; a view-in-browser link is fetched once the same way. There is no account, no email field and no row written anywhere. If you go on to run the free site scan, that one does keep a report so you can come back to it.