What a PDF knows about itself: metadata and the XMP packet
Spec: ISO 16684-1:2019ISO 16684-1:2019Spec: ISO 32000-2ISO 32000-2
At a glance
Section titled “At a glance”Open a modern PDF and it may tell you about itself twice. There is a small, old key/value list called the Document Information dictionary, and there can be a block of XML — the XMP packet — that says much the same thing in a richer, structured form. This page is about those two parallel systems, why both survive, and why archival and search pipelines insist they agree.
The short answer to the title: a PDF knows its title, author, subject, keywords, the tool that made it, and when. It stores that knowledge in two places at once, and the interesting engineering is in keeping them honest.
Why this matters
Section titled “Why this matters”Metadata is the part of a document a human rarely sees and a machine almost always reads. Your operating system’s file preview, a digital-asset manager, a library catalogue, a search index, a legal-discovery tool — many of them read the metadata before, or alongside, the document text, and trust what it says.
So when the two systems disagree — the Info dictionary says one author and the XMP packet says another — something downstream picks one, and you do not get to choose which. A search index may surface the wrong title. An archival validator may reject the file outright. The drift is invisible until a pipeline trips over it, which is the worst time to discover it.
The short version
Section titled “The short version”- A PDF can carry metadata in two parallel systems: the legacy Document Information dictionary and the modern XMP packet of RDF/XML.
- The XMP packet is wrapped in an xpacket processing instruction — a
beginheader and anendtrailer — so a tool can find and, in place, even rewrite it without reparsing the whole file. - Properties live in namespaces:
dc(Dublin Core) for title and creator,xmpfor create and modify dates,pdffor the producer,xmpMMfor document identity and history. - PDF/A requires XMP metadata, and DocInfo entries that have XMP equivalents must match it — a disagreement is a validation failure.
- NextPDF treats the two as one job: it writes both, reads XMP back, and guards the packet’s size, failing closed rather than emitting a malformed file.
How NextPDF approaches it
Section titled “How NextPDF approaches it”This is a synchronization problem dressed up as a
formatting problem. The Document Information dictionary
(Spec: ISO 32000-2, §14.3.3ISO 32000-2 §14.3.3), referenced from the trailer
by the /Info entry, is a flat list of strings: Title, Author, Subject,
Keywords, Creator, Producer, and a couple of dates. It is simple, it predates
XML, and it still rides along in almost every file because so many tools still
read it first.
The XMP packet (Spec: ISO 16684-1:2019, §7ISO 16684-1:2019 §7) is the modern half. It is an XML document — RDF/XML, to be exact — that models the file as a set of named properties grouped into schemas, each schema bound to a namespace (Spec: ISO 16684-1:2019, §6ISO 16684-1:2019 §6). That structure is what the flat dictionary cannot do: a value can be an ordered list, a language-tagged alternative (“title in English, title in French”), or a structured record. In a PDF, that XML lives in a metadata stream attached to the document catalog (Spec: ISO 32000-2, §14.3.2ISO 32000-2 §14.3.2), which is the canonical place a current reader looks.
Three details are worth dissecting, because they are where tools get the packet wrong.
The wrapper. An XMP packet is bracketed by a processing instruction so that,
in formats where the packet is stored as directly searchable bytes, a program can
locate the metadata without a full parse; in PDF specifically, the catalog
metadata stream is the canonical locator.
The begin header carries a byte-order mark that declares the text encoding;
the end trailer carries a flag stating whether the packet is read-only or may
be edited in place. When it is writable, the serializer leaves a run of
whitespace padding after the XML so an editor can grow the content slightly
without shifting every byte that follows. That padding is not decoration — it
is what makes in-place metadata editing possible.
The namespaces. A property is meaningful only against its namespace, and a
handful are near-universal. Dublin Core (dc) holds the title and the creator.
The XMP basic schema (xmp) holds the create and modify dates and the
authoring tool. The PDF schema (pdf) holds the producer string and the
keywords. The media-management schema (xmpMM) holds the document’s identity
and its derivation history — the trail that says “this file came from that
one.” Agreeing on these namespace URIs and property names — usually shown with
conventional prefixes — is the whole point of the core schemas
(Spec: ISO 16684-1:2019, Annex BISO 16684-1:2019 Annex B); two tools that both
speak the Dublin Core title property interoperate without prior arrangement.
The consistency rule. Because both systems can name the same property, they can disagree. The archival profiles refuse to allow that. A PDF/A file must carry an XMP metadata stream, and any Document Information entry that has an XMP equivalent must match it; a disagreement is a validation failure. The practical takeaway is direct: in an archival pipeline, the two are not independent fields but one fact written twice, and they have to stay in step.
NextPDF handles all three as a single concern. The metadata flow is one path, not two competing ones.
- Collect the values onceTitle, author, subject, keywords, creator, producer and dates are set on the document a single time, so there is one source of truth, not two.
- Write the Info dictionaryThe DocInfo writer emits the legacy Title, Author, Subject, Keywords, Creator, Producer and date entries that older tools read first.
- Build the XMP packetThe XMP builder serializes the same values as RDF/XML under dc, xmp, pdf and xmpMM, wrapped in the xpacket header and trailer with writable padding.
- Guard the packet sizeBefore serialization is accepted, the engine checks the packet against a size bound and fails closed with a typed exception rather than emit a malformed or oversized stream.
- Read XMP back to verifyThe XMP reader parses the packet so a pipeline can confirm the engine wrote the metadata it was given — the kind of check an archival validator builds on.
Practical example
Section titled “Practical example”The shape below sets metadata once and lets the engine fan it out to both systems, then reads the XMP title back so a pipeline can inspect it. The size guard is the line that turns “probably fine” into “provably refused if not.”
<?php
declare(strict_types=1);
use NextPDF\Core\Document;use NextPDF\Metadata\Exception\XmpPacketTooLargeException;
$document = Document::createStandalone();
// Set the values ONCE. The engine writes them to both the Info dictionary// and the XMP packet, so the two systems cannot drift apart at the source.$document->setTitle('Annual Report 2026');$document->setAuthor('Records Office');$document->setSubject('Statutory annual filing');$document->setKeywords('annual report, statutory, 2026');
try { // Building the document serializes the XMP packet. The engine guards the // packet size and fails closed: a packet that exceeds the bound is a // typed exception, never a silently truncated or malformed stream. $bytes = $document->getPdfData();} catch (XmpPacketTooLargeException $e) { // Decide deliberately: trim the metadata, not the guarantees. error_log('XMP packet exceeded the size bound: ' . $e->getMessage()); throw $e;}
// Read the packet back. This confirms the XMP the engine serialized carries the// value you set — the kind of integrity check an archival pipeline runs before// it trusts the file. (Both systems are written from one source, so they agree// by construction; reading the XMP back proves it serialized as intended.)$xmp = $document->readXmpMetadata($bytes);$xmpTitle = $xmp->get('dc', 'title'); // 'Annual Report 2026'
if ($xmpTitle !== $document->getTitle()) { throw new \RuntimeException('XMP title does not match the value that was set.');}There is no path here where the two systems quietly diverge: the values enter once, both writers consume the same source, and the reader lets a pipeline check the result.
Common misconception
Section titled “Common misconception”The frequent belief is that the Info dictionary is obsolete and you can ignore it. You cannot — not yet. A great deal of installed software, including some operating-system file previews and older archival tooling, still reads the Info dictionary first or only. Dropping it does not modernize a file; it makes the file look untitled to anything that has not adopted XMP.
The mirror-image mistake is treating the two as independent fields you fill in separately. That is exactly how they drift. They are two serializations of one fact. Write them from one source, or accept that something downstream will pick the version you did not mean.
Limits and boundaries
Section titled “Limits and boundaries”- NextPDF writes both systems and reads XMP back. Its scope is the XMP metadata builder, the DocInfo writer, and an XMP reader. It does not promise to be a general-purpose RDF/XML query engine.
- The XMP packet is size-guarded and fails closed. A packet that exceeds the engine’s bound raises a typed exception. The engine will not emit a truncated, padded-past-limit, or otherwise malformed packet to make an oversized request “fit.”
- Consistency is enforced at write time from one source; it is not magic reconciliation of a file you did not produce. If you import a document whose two systems already disagree, resolving that is your decision, not an implicit rewrite.
- PDF/A’s metadata requirements are part of the archival profile. This page explains the rule; the conformance verdict belongs to a validator, as it always does for archival work. See the archival page for that boundary.
The metadata builder, the DocInfo writer, and the XMP reader are Core capabilities.
| Edition | Availability |
|---|---|
| Core | The XMP metadata builder, the Document Information dictionary writer, and the XMP reader ship in Core, with the size guard that fails closed on an oversized packet — including the PDF/A conformance output and validation that make the XMP metadata stream mandatory and require DocInfo to match it. |
| Pro | Adds batch and templated metadata workflows over the same Core writer and reader. |
| Enterprise | Adds the broader conformance policy and reporting surface across a document estate. |
Related docs
Section titled “Related docs”- Archival and PDF/A — where the XMP packet stops being optional and the DocInfo-to-XMP consistency rule becomes a pass-or-fail requirement.
- Compliance you can hand to an auditor — why metadata that round-trips and agrees with itself is part of an auditable artifact.
- The anatomy of a PDF file — where the trailer, the catalog, and the metadata stream sit in the file structure.
- Streams and filters — the metadata stream is a stream; this is how PDF streams are encoded and kept deterministic.
Glossary
Section titled “Glossary”- Document Information dictionary — the legacy, flat key/value metadata
referenced from the trailer by the
/Infoentry: Title, Author, Subject, Keywords, Creator, Producer, and dates. Predates XMP; still widely read. - XMP — the Extensible Metadata Platform, an XML (RDF/XML) format for describing a resource with named properties grouped into schemas. Standardized as ISO 16684-1.
- xpacket — the processing instruction that wraps an XMP packet, with a
beginheader (encoding marker) and anendtrailer (read-only or writable flag), so a tool can locate and edit the packet without a full parse. - Namespace / schema — a named vocabulary of properties bound to a URI.
Common prefixes:
dc(Dublin Core),xmp(XMP basic),pdf(PDF-specific),xmpMM(media management / document identity). - Metadata stream — the PDF object, attached to the document catalog, that carries the XMP packet. The canonical location a modern reader checks first.
- PDF/A — the archival PDF profile family (ISO 19005). It requires an XMP metadata stream and demands that any Document Information entry with an XMP equivalent match it, or validation fails.