Takumi

PDF/A

Archival output that validators accept

Render a PDF/A document with pdfa.

import {  } from "takumi-pdf";

const  = await (, {
  : "3b",
});

Conforming output includes an sRGB output intent and XMP metadata. Fonts are always embedded and subset, with or without PDF/A.

Levels

LevelPDF versionWhat it adds
"2b"PDF 1.7Basic conformance.
"2u"PDF 1.72b plus guaranteed Unicode mapping.
"2a"PDF 1.72u plus a tagged structure tree.
"3b"PDF 1.72b plus arbitrary file attachments.
"3u"PDF 1.72u plus arbitrary file attachments.
"3a"PDF 1.73u plus a tagged structure tree.
"4"PDF 2.0The PDF 2.0 revision of the standard.
"4f"PDF 2.04 plus arbitrary file attachments.

The u levels add no output cost. Takumi always writes ToUnicode maps.

PDF/A-3 and PDF/A-4f allow arbitrary file attachments. ZUGFeRD and Factur-X electronic invoices expect "3b". See Attachments.

PDF/A-1 is not offered. It prohibits transparency.

Validation runs during rendering. When a document cannot conform, the render fails with the violated rule instead of writing a broken file.

Every level, and PDF/UA-1, passes veraPDF, the reference validator.

Tagged output

tagged defaults to true. Tagged output mirrors Chromium's print-to-PDF.

Set tagged: "ua1" to also validate against PDF/UA-1:

import {  } from "takumi-pdf";

const  = await (, {
  : "2a",
  : "ua1",
  : "en",
  : {
    : "Annual report",
    : "2026-08-06",
  },
});

The structure tree comes from the HTML semantics:

HTMLPDF
h1h6Hn with the heading text as title
p, bare textP
imgFigure with the alt text
img with alt=""artifact (decorative, no element)
aLink, holding the link annotation
ul, ol, liL, LI, LBody
strong, em, codeStrong, Em, Code
page headers and footersartifacts

Heading levels come from nesting, not the tag name. A document that starts with h2 gets an H1. A jump from h1 to h4 becomes H1 then H2. PDF/UA rejects a sequence that skips a level or starts below H1. HTML written for visual styling does this all the time.

Tables are missing from that list. <table> markup is not supported. A table built out of flex rows carries no Table, TR or TH elements, so a screen reader cannot navigate it by row and column. The file still passes PDF/UA-1. The validator checks the tags that are there, not the ones the content deserves.

Set tagged: false to skip the tree when file size matters more than accessibility.

Invalid combinations are TypeScript type errors. pdfa: "2a" and pdfa: "3a" forbid tagged: false. pdfa: "4" forbids tagged: "ua1", because PDF/UA-1 is PDF 1.7-only and PDF/A-4 is PDF 2.0. The 2 levels and "4" forbid attachments. Use "4f" for attachments in PDF 2.0. See Attachments.

Validators require inputs the renderer cannot supply:

  • lang is the document language. A-levels and PDF/UA require it.
  • metadata.title is required by PDF/UA.
  • metadata.creationDate is required by the a levels. Use UTC "YYYY-MM-DD" or "YYYY-MM-DDTHH:MM:SS". A fixed date keeps output byte-identical across runs.

PDF/UA also requires a document outline. Takumi generates it from headings.

Last updated on

On this page