Making accessible PDFs with LaTeX

Carlo Angiuli • February 13, 2026

At the request of several colleagues in my department, I’m presenting my findings on how to produce accessible PDFs containing mathematics, using the LaTeX typesetting system. (Or at least, PDFs that the Ally tool on Canvas says are accessible.)

Qualifications: I have used LaTeX a lot, for a long time. I consider myself a moderately sophisticated LaTeX user, but I am definitely not remotely an expert on LaTeX’s internals or on accessibility. On the plus side, I am currently teaching a theoretical course on programming languages that has a 96% Ally accessibility score on Canvas, including a handful of LaTeX-generated PDFs scoring 100%.

Background

In April 2024, the federal government updated the Americans with Disabilities Act to require that the web content of state and local governments meet certain accessibility guidelines. This includes Indiana University, effective April 24, 2026. In particular, all course content on Canvas is supposed to meet accessibility guidelines by that deadline, whether or not you have a student who asks for it.

The WCAG 2.1 Level AA guidelines are extensive, but perhaps a useful oversimplification is to say that your documents need to work with screen readers by including metadata such as alt text for images, the proper reading order for text elements, how section headings are organized, and even what language the document is written in. IU’s accessibility website explains how to do this for documents written in Office, err, I mean, “Microsoft 365 Copilot.”

PDF has gradually added accessibility features over the past two decades (such as “Tagged PDF” metadata) but the PDF/UA-2 standard from 2024 took a huge step forward, building on new features of the PDF 2.0 standard from 2017. Particularly relevant to us is the ability to include MathML as “alt text” for mathematical expressions.

The LaTeX Tagged PDF Project

The good news is that a lot of the required metadata is implicit, or can easily be made explicit, in LaTeX source files. The bad news is that propagating this information to generated PDFs has required extensively modifying the internals of existing (La)TeX engines, which generally discarded all inessential data as quickly as possible due to 1980s-era memory constraints. The worse news is that these modifications are still ongoing and many major packages are not yet compatible.

These efforts—the LaTeX Tagged PDF Project—started in earnest in 2020. If you’re interested in learning more about it, there’s an article from 2020 outlining the original plan, an update article from 2024, and a talk from 2025. Although the project is far from complete, TeX Live 2025 can produce fully-compliant PDFs, and TeX Live 2026 (releasing March 7, 2026) will work even better.

Aside: To give you an idea of how deeply inaccessible early versions of LaTeX are, prior to TeX Live 2014, LaTeX engines did not emit spaces between words; they just placed each visible character at the right coordinate, skipping some extra space between words. (See pdfTeX’s \pdfinterwordspaceon option.)

Only two engines currently (and seemingly will ever) support accessible PDFs: pdfLaTeX and LuaLaTeX. If you’re not sure what you use, it’s probably pdfLaTeX. XeLaTeX is no longer actively developed, and LaTeX (the original one that produces DVI files)…well, that’s not going to work for obvious reasons. I’ve mostly stuck with pdfLaTeX through the years, but I strongly recommend LuaLaTeX for this.

Finally, I find it helpful to think of LaTeX tagged PDF support as having two distinct components:

Please just tell me what to do

OK, OK. All of this context is important because you will run into issues, and I found it very hard to understand those issues until I understood everything I said above. But let’s get to it.

You need to use TeX Live 2025 or newer. I personally like to do a “full” install of TeX Live outside of any package system so that I can easily maintain multiple versions. Parts of these instructions also require you to update the 2025 distribution with tlmgr update --all, because this functionality is being actively developed.

You can also jump straight to the usage instructions, but I’ve found that it’s easier to debug if you incrementally turn on features as described below.

Step 1: PDF 2.0

To activate the PDF management functionality, add this as the first line of your LaTeX file and try compiling with LuaLaTeX (or pdfLaTeX):

\DocumentMetadata{lang=en-US}

If you use (m)any packages, your file may well not compile. If it does compile, then the output should be PDF 2.0 instead of the usual PDF 1.5 or 1.7, and it will score slightly higher on Canvas. (You can check the version easily with file.)

In the more likely event that it doesn’t, try to figure out what’s causing the error. Check the list of package compatibility with tagging, and if appropriate, open a GitHub issue with the LaTeX Tagged PDF Project. I (and many PL folks) extensively use a package called mathpartir that was untested until I opened an issue. (Note to mathpartir users: use the patch to the mathpar environment suggested by David Carlisle in this GitHub comment.)

The most problematic packages are those that modify LaTeX internals and/or reimplement a lot of core functionality; some of these may never be fully supported, and the Tagged PDF Project may in fact hasten their demise independently of whether you want accessible PDFs. For an example of modifying internals, I will probably have to switch from the unmaintained cleveref to zref-clever soon due to some regressions in TeX Live 2025. For an example of reimplementing core functionality, I can only hope that memoir will eventually be supported. And beamer is completely hopeless.

Step 2: Basic tags

Now we have a PDF 2.0 file tagged only with its language. That was the hardest part for me: I had to open a ticket about mathpartir, tweak a few packages, and debug inconsistencies between pdfLaTeX and LuaLaTeX. (The diffpdf package on Ubuntu was quite helpful for this.)

To actually tag your content, just replace the first line with:

\DocumentMetadata{lang=en-US,tagging=on}

This enables automatic tagging for many basic LaTeX features: headings, figures, tables, etc. You can use TeX Live’s show-pdf-tags command-line utility to see what is and isn’t tagged.

You will have to manually tag images (with alt text) and tables (by indicating which rows are “header rows”), as described in the usage instructions. Note that Ally complains about presentation tables without header rows. (I had to mistag some tables that I use for alignment in order to satisfy Ally.)

Step 3: Math tags

At this point, Ally will complain that all of the mathematical expressions in your document are “images missing alternative descriptions.” (I’m not sure why this is the warning message, because they are definitely not images.)

To make our mathematics accessible, we can embed alternative MathML and/or plain text into the PDF. The former is the best approach, but only the latter satisfies Ally. It’s easy enough to do both in LuaLaTeX, by replacing the first line with:

\DocumentMetadata{lang=en-US,tagging=on,tagging-setup={math/setup=mathml-SE,math/alt/use}}

The math/alt/use part tags mathematical expressions with their actual LaTeX source as their plain alt text. (Be aware that this exposes the names of your macros, your shameful LaTeX code, etc.) The math/setup=mathml-SE part uses luamml to generate an intermediate file called filename-luamml-mathml.html with MathML representations of every mathematical expression, and then embed these in the PDF. These two options are independent.

At this point in the process, my PDFs score 94-100% on Ally.

Peculiarities of the Ally Course Accessibility Report

I’ll close with a couple remarks specific to the Ally tool. First, as mentioned above, it seems to not acknowledge presentation tables or MathML.

More significantly, it took over a week to notice that files have changed or been deleted. In the testing process I repeatedly deleted, renamed, and uploaded files called ps1.pdf and the Ally tool got extremely confused, separately cataloging a dozen different accessibility ratings all linking to the same exact PDF. (One stale rating has persisted a month and counting.) To avoid this issue when reuploading PDFs, you have to open the Ally report for a PDF with a sub-100% score and then reupload using the button on that screen specifically.

Let me know if you found this helpful, and if you have anything to add!