PDF/UA validation in Java, Python, .NET SDKs, and a PDF server
Table of contents
- A PDF can declare PDF/UA (accessibility) conformance in its metadata without actually meeting the standard — files edited after conversion, produced by third-party tools, or assembled from mixed sources routinely violate the requirements they claim.
- Nutrient’s Java SDK, Python SDK, and .NET SDK now validate a document against the conformance level it claims, or against any level requested, and return a detailed, machine-readable report listing every rule violation found.
- Nutrient Document Engine adds the same capability as an HTTP API:
POST /api/validate_pdfuaaccepts an uploaded file, a remote URL, or a document already stored on the server and returns a PDF/UA-1 conformance report. - A pipeline can now check conformance and produce a report for it, rather than trusting the file’s own claim.
Explore Nutrient’s accessibility tools
A PDF can say it’s PDF/UA-conformant and be wrong. The standard works through a declaration: A file carries an identifier in its metadata — an XMP entry such as pdfuaid:part=1 — but nothing forces that declaration to be true. A file converted by one tool, edited by another, and merged by a third can carry a PDF/UA identifier while its structure tree, reading order, or tagging no longer qualifies.
That gap matters most for PDF/UA, the accessibility standard, because a validator can only check what’s mechanically checkable: structure, tags, reading order, and alternative text. It can’t judge whether that alternative text describes the image, or whether a heading hierarchy makes sense to a person navigating by screen reader. Regulatory frameworks that reference PDF/UA — Section 508 in the United States, the European Accessibility Act, and Web Content Accessibility Guidelines (WCAG)-based procurement requirements — treat it as a testable technical target rather than a substitute for human review. A validator does something narrower than proving a document accessible: It checks the specific rules the standard defines and reports which ones a file fails.
Nutrient’s Java, Python, and .NET SDKs — the embedded libraries developers use to generate, convert, and edit PDFs inside their own applications — now do that check natively. Document Engine, a server for the same kind of PDF work (self-hosted, cloud, or managed), exposes the same check as an HTTP API. Previously, verifying a document’s accessibility claim required a separate third-party tool.
What this looks like in practice
PDF/A, the archival standard, covers long-term renderability rather than accessibility. PDF/UA-1 requires a tagged structure tree, a defined reading order, and alternative text present on meaningful images (the rule checks that it exists, not that it describes the image) — none of which a PDF/A-conformant file is strictly required to have. A file can satisfy every PDF/A rule and fail PDF/UA-1 outright.
A PDF/A archival pipeline converts a document, tags it with a PDF/A identifier, and stores it as compliant. Running that same file through PDF/UA-1 accessibility checks asks a different question, and it often fails.
Validating against a claimed conformance level catches documents whose claim is false. Validating against a level the document never claimed works the same way — for example, checking whether a PDF/A archive also meets PDF/UA-1, even though it never declared accessibility conformance. Both checks return the same kind of output — a pass/fail result and a report naming every rule the file violates — so a pipeline can act on the specific failure instead of a rejection with no detail.
One validator, two standards, on Java and Python
Nutrient’s Java and Python SDKs validate PDF/UA-1 (and, for other use cases, PDF/A) through the same API. Binding a validator to a document and calling validate() checks the file against whatever conformance level it claims in its metadata:
PdfValidator validator = PdfValidator.set(document);
PdfValidationResult result = validator.validate();System.out.println("Document is valid: " + result.getIsValid());System.out.println("Validated conformance: " + result.getValidatedConformance());
Files.writeString(Path.of("report.xml"), result.getReport());The result carries three things:
- Whether the document is valid.
- Which conformance level it was checked against.
- An XML report that lists every violation when it isn’t valid.
If the document claims no conformance at all, nothing runs against it. The result reports the file as not valid, and the report says there was nothing to validate.
To check a level the document doesn’t claim, set it explicitly before validating:
validator.setConformance(PdfValidationConformance.PdfUa1);
PdfValidationResult uaResult = validator.validate();System.out.println("PDF/UA-1 conformant: " + uaResult.getIsValid());In Python, the same check looks like this:
validator = PdfValidator.set(document)
result = validator.validate()print(f"Document is valid: {result.is_valid}")print(f"Validated conformance: {result.validated_conformance}")Forcing a specific level works the same way, through a conformance property instead of Java’s setConformance() method.
Explicit conformance checks on .NET
Nutrient .NET SDK — formerly GdPicture.NET SDK — already validates PDF/A conformance through IsValidPDFA() and CheckPDFAConformance(). Internally, its class names still use the GdPicture prefix. IsValidPDFUA() and CheckPDFUAConformance() now add the PDF/UA-1 counterpart, following the same pattern rather than introducing a new object model. Three method families cover the flow:
GetPDFConformance()reads what a document claims.- The
IsValid*methods validate against that claim. - The
Check*Conformancemethods force a specific level.
Each returns a Boolean and writes the same kind of machine-readable XML report:
string uaReport = string.Empty;bool isUaConformant = pdf.CheckPDFUAConformance(PdfValidationConformance.PDF_UA_1, ref uaReport);Console.WriteLine($"PDF/UA-1 validation result: {isUaConformant}");The check and the output are the same as in Java and Python, but the .NET surface splits them into named methods instead of one object with a settable conformance target.
Validation as a server API on Document Engine
Document Engine reaches the same result over HTTP instead of an in-process SDK call. POST /api/validate_pdfua accepts an uploaded file, a remote URL, or a document already stored in Document Engine, and it returns a machine-readable PDF/UA-1 conformance report:
curl -X POST http://localhost:5001/api/validate_pdfua \ -H "Authorization: Token token=<API token>" \ -F document=@/path/to/output-pdfua.pdfA pipeline can call the check directly, without embedding an SDK in the service that handles it — running it after auto-tagging a batch of converted documents, or as a gate before a file leaves the system.
What this changes
Validation doesn’t make a document more accessible; it won’t fix a missing heading or write better alternative text. That’s what PDF/UA auto-tagging and PDF/UA conversion are for — validation is the check that confirms the result, whichever tool produced it. What used to take a separate tool now runs as the same kind of call as generating the document, on the four platforms that already produce and convert PDFs. AI auto-tagging, which generates alternative text for images, is planned for a future release.
A compliance or accessibility team can point to a report for a specific file, naming each rule it fails, instead of a general belief that its documents are accessible. For a procurement reviewer citing Section 508 or the European Accessibility Act, a validation report is stronger evidence than a claim embedded in the file’s own metadata.
Getting started
- PDF/UA — What the standard requires, and how it differs from WCAG.
- Validate PDF conformance (Java) — The full guide, including all supported PDF/A and PDF/UA-1 targets.
- Validate PDF conformance (Python) — The same capability with Python syntax.
- Validate PDF conformance (.NET) — The GdPicture-based method reference.
- Document Engine 1.18 release notes — The
validate_pdfuaendpoint and everything else that shipped alongside it.
See Nutrient’s accessibility tools
FAQ
No. A passing report confirms the file follows PDF/UA-1’s structural rules. It doesn’t confirm the content is actually usable, since no automated check can judge whether alternative text is meaningful or a heading order makes sense to a real reader. Pair validation with human review rather than treating it as a replacement.
The Java SDK, Python SDK, and .NET SDK validate it natively. Document Engine exposes the same check as a server API, POST /api/validate_pdfua, which accepts an uploaded file, a remote URL, or an existing Document Engine document.
Yes, on the Java, Python, and .NET SDKs. In addition to validating against whatever level the document already declares, they can check a level it never claimed — for example, testing a PDF/A archive against PDF/UA-1 even though it never declared accessibility conformance. Document Engine’s endpoint checks PDF/UA-1 specifically, regardless of what the document claims.
Yes, directly — validation is an SDK method call or a Document Engine API request, so using it in a pipeline requires engineering integration. A compliance or procurement team without in-house engineering resources should ask its engineering team to add the check or route documents through a Document Engine deployment already wired into the pipeline.