This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /blog/pdf-ua-validation.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. PDF/UA validation in Java, Python, .NET SDKs, and a PDF server

Table of contents

    PDF/UA validation in Java, Python, .NET SDKs, and a PDF server
    TL;DR
    • 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_pdfua accepts 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*Conformance methods 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:

    Terminal window
    curl -X POST http://localhost:5001/api/validate_pdfua \
    -H "Authorization: Token token=<API token>" \
    -F document=@/path/to/output-pdfua.pdf

    A 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

    See Nutrient’s accessibility tools

    FAQ

    Does passing PDF/UA-1 validation mean a document is fully accessible?

    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.

    Which Nutrient products can validate PDF/UA conformance?

    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.

    Can validation check a conformance level a document doesn’t claim?

    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.

    Does a compliance team need engineering help to use this?

    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.

    Pavel Bogachevskyi

    Pavel Bogachevskyi

    Senior Product Marketing Manager

    Pavel is a passionate marketing professional dedicated to effectively communicating product values to customers. He has a Ph.D. in philosophy, which brings a unique perspective to his work. In his downtime, Pavel enjoys indulging in his love for rum.

    Explore related topics

    Try for free Ready to get started?