PDF information and metadata

View Source

Use NativeElixirPdfUtilities.Info to read metadata, count pages, check page sizes, or update a document's title and other information.

alias NativeElixirPdfUtilities.Info

{:ok, pdf} = File.read("report.pdf")
{:ok, information} = Info.get(pdf)
{:ok, page_count} = Info.page_count(pdf)

Read metadata

Info.get/1 returns a map with these keys. Missing fields are nil.

KeysReturned value
:title, :author, :subject, :keywords, :producerString or nil
:creation_date, :modification_dateNaiveDateTime or nil

Dates retain the document's wall-clock time. A timezone suffix is validated, but the returned date is not converted to UTC. XMP metadata is not read.

Updating information

{:ok, updated_pdf} =
  Info.put(pdf,
    title: "Monthly statement",
    author: "Finance team",
    keywords: ["statement", "monthly"],
    modification_date: DateTime.utc_now()
  )

File.write!("updated.pdf", updated_pdf)

Pass a map or keyword list using the fields above. Omitted fields stay unchanged; nil removes a field. Keywords accept a string or a list of strings. Text must be valid UTF-8. Dates accept Date, NaiveDateTime, DateTime, ISO 8601 strings, or valid PDF date strings.

The update preserves page content and unrelated information. It appends a revision, so old metadata remains in the file's earlier bytes. This is not secure deletion and may affect existing signatures. XMP is not updated. An empty patch returns the original binary.

Page count and geometry

{:ok, count} = Info.page_count(pdf)
{:ok, pages} = Info.page_sizes(pdf)

Enum.each(pages, fn page ->
  IO.inspect({page.page_number, page.width, page.height, page.rotation})
end)

Each size entry contains:

FieldMeaning
:page_numberOne-based page number
:width, :heightMediaBox dimensions after rotation and UserUnit scaling
:unitAlways :point, or 1/72 inch
:rotation0, 90, 180, or 270 degrees
:media_box%{left: ..., bottom: ..., right: ..., top: ...} before UserUnit scaling

Dimensions use the MediaBox, not the visible CropBox. For placing stamps, see stamp coordinates.

Encryption status

{:ok, encrypted?} = Info.encrypted?(pdf)

This checks encryption without decrypting the document. Other information operations require an unencrypted PDF.

Failures return the shared diagnostic tuple. See PDF input support and metadata limits for restrictions.