Skip to content

WeasyPrint pdf_variant — PDF/A and PDF/UA Reference

WeasyPrint can emit PDF files that conform to the PDF/A archival standards and the PDF/UA accessibility standard. Which one you get is controlled by a single argument, pdf-variant. This page documents every value that argument accepts, what each conformance level actually guarantees, and what your HTML must contain for the output to be valid.

PdfBroker.io runs WeasyPrint as a hosted REST API, so the same argument is available without installing WeasyPrint, Pango, or any font tooling locally. Everything below applies both to the WeasyPrint command line (--pdf-variant) and to the weasyPrintToPdfArguments object in a PdfBroker.io API request.

Syntax

In a PdfBroker.io API request, pdf-variant is a key inside weasyPrintToPdfArguments:

{
    "htmlBase64String": "PCFET0NUWVBFIGh0bWw...",
    "weasyPrintToPdfArguments": {
        "pdf-variant": "pdf/a-2b"
    }
}

The equivalent on the WeasyPrint command line:

weasyprint --pdf-variant pdf/a-2b input.html output.pdf

The value is lowercase and includes the slash. Only one variant can be requested per document. If a file must be both archival and accessible, that is a single variant too — see combining PDF/A and PDF/UA below. An unrecognised value is rejected with a 400 Bad Request; the list under accepted values is exhaustive.

Accepted values

Value Standard Based on Use it for
pdf/a-1b PDF/A-1b (ISO 19005-1) PDF 1.4 The most conservative and most widely accepted archival level. Choose this when an authority specifies "PDF/A" without a version, or when the receiving system is old.
pdf/a-2b PDF/A-2b (ISO 19005-2) PDF 1.7 The common default for new archival work. Adds JPEG2000, transparency, and layers over A-1b, and allows PDF/A files to be embedded inside one another.
pdf/a-3b PDF/A-3b (ISO 19005-3) PDF 1.7 Identical to A-2b except that arbitrary files may be embedded. This is the level used for electronic invoicing formats that carry a machine-readable XML payload inside the PDF.
pdf/a-2u PDF/A-2u (ISO 19005-2) PDF 1.7 Level B plus a guarantee that all text maps to Unicode, so the document can be searched and copied reliably. A cheap upgrade over A-2b when the archive is meant to be read, not just stored.
pdf/a-3u PDF/A-3u (ISO 19005-3) PDF 1.7 A-3b with the same Unicode guarantee. The usual choice for e-invoicing profiles that require both an embedded XML payload and extractable text.
pdf/a-1a PDF/A-1a (ISO 19005-1) PDF 1.4 Level A: everything level B guarantees, plus a tagged structure tree and Unicode mapping. Archival and accessible in one file.
pdf/a-2a PDF/A-2a (ISO 19005-2) PDF 1.7 The practical choice when a document must satisfy an archival policy and an accessibility requirement at the same time.
pdf/a-3a PDF/A-3a (ISO 19005-3) PDF 1.7 Level A with embedded attachments allowed — an accessible e-invoice carrying its own XML.
pdf/a-4u PDF/A-4 (ISO 19005-4) PDF 2.0 The baseline PDF/A-4 level. PDF/A-4 dropped the A/B lettering and requires Unicode mapping of all text, which is why the value carries a "u". Choose it only when the recipient has confirmed PDF 2.0 support — validator and reader coverage is still thinner than for A-2b.
pdf/a-4f PDF/A-4f (ISO 19005-4) PDF 2.0 PDF/A-4 with arbitrary embedded files allowed. The PDF 2.0 successor to A-3b for e-invoicing.
pdf/a-4e PDF/A-4e (ISO 19005-4) PDF 2.0 The engineering profile, intended for technical documentation carrying 3D and rich-media content. Rarely what a web document needs.
pdf/ua-1 PDF/UA-1 (ISO 14289-1) PDF 1.7 Accessibility. Produces a tagged PDF with a semantic structure tree that screen readers can navigate. Relevant to the European Accessibility Act. This is the value to use unless a recipient has specifically asked for UA-2.
pdf/ua-2 PDF/UA-2 (ISO 14289-2) PDF 2.0 The PDF 2.0 revision of PDF/UA. Same purpose, newer tag model. Tooling support is still catching up, so verify that your validator and your recipient handle it before switching.
pdf/x-1a PDF/X-1a:2003 (ISO 15930-4) PDF 1.4 Print production. The most restrictive print exchange profile — CMYK or spot colour only, everything embedded.
pdf/x-3 PDF/X-3:2003 (ISO 15930-6) PDF 1.4 Print production allowing colour-managed RGB in addition to CMYK.
pdf/x-4 PDF/X-4 (ISO 15930-7) PDF 1.6 The modern print exchange profile: transparency and layers are preserved rather than flattened. Ask your printer which profile they want before choosing.
pdf/x-5g PDF/X-5g (ISO 15930-8) PDF 1.6 X-4 extended with references to external graphic objects. Only for workflows that have explicitly asked for it.

The letter at the end: a, b and u

PDF/A-1 through A-3 define conformance levels within each version. Level B (basic) guarantees that the document will look the same in future — fonts embedded, colour spaces defined, no external dependencies. Level U adds a guarantee that all text maps to Unicode. Level A (accessible) adds a tagged structure tree on top of that. PDF/A-4 dropped the lettering: it requires Unicode throughout, and the remaining profiles are f (embedded files) and e (engineering).

There is no pdf/a-4b. Requesting it returns an error — use pdf/a-4u for baseline PDF/A-4.

What your HTML must provide

Requesting a variant does not by itself make a document conformant. WeasyPrint handles the PDF-level mechanics — font embedding, colour space declaration, XMP metadata, the structure tree — but it can only work with what the HTML gives it. These are the requirements that fail most often in practice.

For all PDF/A variants

  • Fonts must be embeddable. Every font used has to be embedded in full. Fonts with licence flags that forbid embedding will fail validation. Web-safe font stacks that fall back to a system font are a common cause — declare the font explicitly and supply it as a resource.
  • No external references at render time. Images, stylesheets and fonts referenced by URL are fetched during rendering, but a network failure produces a silently incomplete document. Send images as Base64 resources instead.
  • Transparency is not allowed in PDF/A-1b. CSS opacity, rgba() colours, and PNGs with an alpha channel will break A-1b conformance. They are permitted from A-2b onward.
  • Document metadata. A <title> element is required. Supply <html lang="..."> as well — it is mandatory for PDF/UA and good practice everywhere.

Additionally for tagged output (pdf/ua-1, pdf/ua-2 and the level A variants)

  • Semantic HTML throughout. The structure tree is generated from your markup. <div> elements styled to look like headings produce an untagged document that passes nothing. Use real <h1><h6>, <p>, <ul>, <table>.
  • Heading hierarchy without gaps. Exactly one <h1>, and no skipping from <h2> to <h4>.
  • Alt text on every image. An alt attribute is required on each <img>. Purely decorative images should carry an empty alt="" so they are marked as artifacts rather than left untagged.
  • Table headers with scope. Use <th scope="col"> or scope="row" so cell relationships survive into the tag tree.
  • A language attribute. <html lang="sv"> or equivalent. Mark passages in another language with lang on the element.
  • Meaningful link text. "Read more" repeated twelve times is valid PDF/UA but fails the human review that usually accompanies a compliance audit.

Combining PDF/A and PDF/UA

A document that must be both archival and accessible — increasingly common for public-sector records in the EU — is served by a single PDF/A level A variant. pdf/a-2a is the usual choice: it claims PDF/A-2 conformance in the document metadata and emits the tagged structure tree that accessibility rests on. Use pdf/a-3a instead when the file also carries an embedded attachment.

Level A output is only as good as the markup behind it, so the PDF/UA requirements below apply in full: semantic elements, an unbroken heading hierarchy, alt text, table scopes, a language attribute. If the requirement is a formal PDF/UA claim rather than an archival one, request pdf/ua-1 and write the HTML to satisfy the PDF/A rules as well — embeddable fonts, no external references, complete metadata. Validate against your specific requirement either way; the two standards overlap but neither implies the other.

Examples

C# with PdfBroker.Client

// Install: dotnet add package PdfBroker.Client
using PdfBroker.Client;

var client = new PdfBrokerClientService("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

var html = File.ReadAllText("invoice.html");
var htmlBase64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(html));

byte[] pdf = await client.WeasyPrintAsByteArrayAsync(new
{
    htmlBase64String = htmlBase64,
    weasyPrintToPdfArguments = new Dictionary<string, string>
    {
        ["pdf-variant"] = "pdf/a-3b"
    }
});

await File.WriteAllBytesAsync("invoice.pdf", pdf);

Python

import base64, requests

token = requests.post("https://login.pdfbroker.io/connect/token", data={
    "grant_type": "client_credentials",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
}).json()["access_token"]

html = open("report.html", "rb").read()

resp = requests.post(
    "https://api.pdfbroker.io/api/pdf/weasyprint",
    headers={"Authorization": "Bearer " + token},
    json={
        "htmlBase64String": base64.b64encode(html).decode(),
        "weasyPrintToPdfArguments": {"pdf-variant": "pdf/ua-1"},
    },
)

open("report.pdf", "wb").write(resp.content)

cURL

HTML_BASE64=$(base64 -w0 document.html)

curl -X POST https://api.pdfbroker.io/api/pdf/weasyprint \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"htmlBase64String\": \"$HTML_BASE64\",
    \"weasyPrintToPdfArguments\": { \"pdf-variant\": \"pdf/a-2b\" }
  }" \
  --output document.pdf

Verifying the output

Do not assume conformance because the request succeeded. Validate the file with a tool that PdfBroker.io does not control.

  • veraPDF — the open source reference validator for PDF/A and PDF/UA, developed by the Open Preservation Foundation together with the PDF Association — the same people who maintain the ISO standards. Command line and desktop. This is the tool most auditors use.
  • PAC (PDF Accessibility Checker) — free Windows tool from axes4 for PDF/UA and WCAG, with a screen reader preview and a visual view of the tag tree that makes structural problems obvious.
  • Adobe Acrobat Pro — its preflight profiles cover PDF/A and its accessibility checker covers much of PDF/UA.

Validators disagree more often than you would expect — the same document can pass one and fail another, because each interprets parts of the ISO text differently. For anything going into a compliance review, run at least two.

A useful habit is to run veraPDF in CI against a representative document from each template. Conformance breaks quietly — a designer swapping in a new font is enough.

Common failures

Validation fails on font embedding
A font in the CSS stack was not available and a substitute was used, or a font's licence forbids embedding. Declare fonts explicitly and supply them as resources rather than relying on the rendering host.
Transparency errors on pdf/a-1b
Remove opacity, rgba() and alpha-channel images, or move to pdf/a-2b, which permits them.
PDF/UA validation reports untagged content
Content produced by CSS ::before and ::after, or laid out with positioned <div> elements, may not map to a semantic tag. Rewrite the affected region with real elements.
The request fails with 400 Bad Request
The variant value is not one the engine recognises. pdf/a-4b is the common case — it is not a real conformance level, since PDF/A-4 dropped the A/B lettering. Use pdf/a-4u, or pick a value from accepted values.
The document renders but ignores pdf-variant
Check spelling and case — the key is pdf-variant, the value is lowercase with a slash, and it belongs inside weasyPrintToPdfArguments, not at the top level of the request.
JavaScript-generated content is missing
WeasyPrint does not execute JavaScript. Render dynamic content server-side before sending the HTML. If you need JavaScript, use the wkhtmltopdf service — but note that it cannot produce PDF/A or PDF/UA output.