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)
figure, figcaptionone Figure holding a Caption
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. Flex-row tables omit Table, TR and TH elements. Screen readers cannot navigate them by row or column. The file still passes PDF/UA-1, because the validator only checks the tags that are there.

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

PDF/UA-2

tagged: "ua2" validates against PDF/UA-2 instead. The standard is PDF 2.0 only, so it pairs with pdfa: "4", pdfa: "4f", or plain PDF.

import {  } from "takumi-pdf";

const  = await (, {
  : "4",
  : "ua2",
  : "en",
  : {
    : "Annual report",
    : "2026-08-08",
  },
});

Links and outline entries target structure elements, not page positions. Reading order survives when a viewer follows one.

What combines with what

Invalid combinations are TypeScript type errors. PDF/UA-1 uses PDF 1.7. PDF/A-4 and PDF/UA-2 use PDF 2.0. The two generations never mix.

pdfataggedattachments
unsetfalse, true, "ua1", "ua2"yes
2b, 2ufalse, true, "ua1"no
2atrue, "ua1"no
3b, 3ufalse, true, "ua1"yes
3atrue, "ua1"yes
4false, true, "ua2"no
4ffalse, true, "ua2"yes

See Attachments.

Validators require inputs the renderer cannot supply:

  • lang is the document language. A-levels and PDF/UA require it. PDF/UA-2 fails the render without it. A passage in another language needs its own lang attribute.
  • 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