How to convert html to pdf while preserving the meta information?

Using browser’s save as pdf function will lose meta information in the html file. Instead, you may use WeasyPrint which preserves the meta information of the html file, i.e., the stuff in <title></title> will become the Title field of the meta information in the converted pdf.

pip install weasyprint
from weasyprint import HTML

HTML('index.html').write_pdf('result.pdf')
1. Standard Metadata (Automatic Mapping)

You can specify standard properties like Title, Author, Description (Subject), Keywords, and Dates using the tags listed below:

<!DOCTYPE html>
<html lang="en"> <!-- Sets PDF Language attribute -->
<head>
    <meta charset="UTF-8">
    
    <!-- Standard PDF Fields -->
    <title>Monthly Financial Report</title>
    <meta name="author" content="John Doe">
    <meta name="description" content="A summary of Q1 financial performance.">
    <meta name="keywords" content="finance, report, Q1, revenue">
    <meta name="generator" content="Company Reporting Tool">

    <!-- PDF Creation and Modification Dates (W3C ISO 8601 Profile format) -->
    <meta name="dcterms.created" content="2026-08-22T09:30:00Z">
    <meta name="dcterms.modified" content="2026-08-22T10:00:00Z">
</head>
<body>
    <h1>Financial Report</h1>
</body>
</html>
2. Custom Metadata
If you need to include proprietary or non-standard metadata tags (e.g., <meta name="invoice-id" content="INV-12345">), WeasyPrint will ignore them by default. You must explicitly tell WeasyPrint to embed them.
Via the Command Line
Add the --custom-metadata flag:
weasyprint input.html output.pdf --custom-metadata
You may encounter this problem:
WeasyPrint could not import some external libraries.
OSError: cannot load library ‘libgobject-2.0-0’: error 0x7e. Additionally, ctypes.util.find_library() did not manage to locate a library called ‘libgobject-2.0-0’
You need to execute the standalone WeasyPrint.exe instead of the one accompanied by the WeasyPrint python lib which requires the installation of GTK runtime.
Via the Python API
Pass the custom_metadata=True argument to the write_pdf() function:
from weasyprint import HTML

html = HTML('input.html')
html.write_pdf('output.pdf', custom_metadata=True)
Troubleshooting Tip
If your metadata tags are being ignored and not showing up in the PDF properties, check your backend dependencies. WeasyPrint relies on Cairo to write PDF metadata, which requires Cairo version 1.15.4 or newer to function correctly.

How to tell if a pdf file has an external XMP metadata file embedded?

An “external” XMP metadata file becomes an embedded XMP data stream once it is injected inside a PDF.
Because XMP data is structured as plain-text XML, it is wrapped in an <?xpacket begin=...?> processing instruction. You can identify its presence using several quick methods, ranging from basic text searches to professional tools.

Method 1: The Quick “Fingerprint” Test (No Tools Required)
XMP packets are deliberately designed with a readable “magic fingerprint” so tools can scan them without parsing the whole PDF structure. You can check for this text directly. [1]
  • On Linux / macOS Terminal: Run the grep command to look for the XMP packet header:

    grep -a "<?xpacket" your_file.pdf

    If this returns lines of text containing XML schema definitions (like xmlns:xmp=... or xmlns:dc=...), the PDF contains embedded XMP metadata.

  • On Windows PowerShell:
    Select-String -Path .\your_file.pdf -Pattern "<?xpacket" -AllMatches
    
Method 2: Using Adobe Acrobat
If you prefer a visual interface, you can find the complete XML block natively within Adobe software:
    1. Open the PDF in Adobe Acrobat Pro or Standard.
    2. Press Ctrl + D (Windows) or Cmd + D (macOS) to open Document Properties.
    3. Under the Description tab, click the Additional Metadata… button near the bottom right.
    4. Click Advanced in the sidebar. If an XMP packet exists, you will see expandable drop-downs showing structures like http://purl.org/dc/elements/1.1/ (Dublin Core) or pdfx: namespaces.


Method 3: Programmatically via Python
If you are automating a processing pipeline (like verifying a WeasyPrint output), use the pikepdf library. It explicitly handles the handoff between traditional PDF /Info dictionaries and embedded XMP streams.
import pikepdf

with pikepdf.open("your_file.pdf") as pdf:
    try:
        # Attempt to access the root XMP metadata stream
        xmp_data = pdf.open_metadata()
        
        # Check if the stream actually contains data keys
        if len(xmp_data.keys()) > 0:
            print("Success: Embedded XMP metadata found!")
            print(f"Sample key (CreatorTool): {xmp_data.get('xmp:CreatorTool')}")
        else:
            print("The XMP metadata container exists but is empty.")
            
    except pikepdf.PdfError:
        print("No XMP metadata stream found in the PDF catalog.")
Method 4: Using ExifTool (Command Line)
ExifTool is the industry-standard free command-line utility for identifying embedded metadata.
Run the command to extract only the XMP-specific tags:
bash
exiftool -xmp:all your_file.pdf
  • If the terminal yields fields like XMP Toolkit, Creator Tool, or Rights, the external XMP structure is successfully embedded.
  • If it outputs absolutely nothing, no XMP stream is active inside the document.

How to tell if structural PDF tags exist in a pdf file?

To determine if a PDF file contains structural tags (which are required for Section 508, PDF/UA, and screen-reader accessibility), the document must have a MarkInfo dictionary with its Marked key set to True, alongside a physical StructTreeRoot dictionary in its internal catalog.
You can check for these structural tags using a PDF viewer, a command-line tool, or programmatically via Python.

Method 1: The Quick Visual Test (Adobe Acrobat / Foxit)
You can check the document properties using any standard PDF desktop reader: [1, 2]
    1. Open the PDF file in Adobe Acrobat Reader or Foxit PDF Editor. [1, 2]
    2. Press Ctrl + D (Windows) or Cmd + D (Mac) to open the Document Properties window. [1]
    3. Look at the Description tab. [1]
    4. At the bottom-left, locate the Tagged PDF field:
        • Yes means structural elements exist.
        • No means the PDF lacks a structural reading order. [1, 2, 3]

To see the layout structure itself in Acrobat Pro, navigate via the application menu to View > Show/Hide > Navigation Panels > Tags.

Method 2: Programmatically via Python (pypdf or pikepdf)
If you are verifying your WeasyPrint backend automation workflows, you can check for the explicit PDF boolean flag using a Python script.
Using pypdf
from pypdf import PdfReader

reader = PdfReader("your_file.pdf")

# Extract the base document catalog mapping
catalog = reader.trailer["/Root"]

# A tagged PDF requires /MarkInfo to be present and marked True
is_tagged = False
if "/MarkInfo" in catalog and "/Marked" in catalog["/MarkInfo"]:
    is_tagged = catalog["/MarkInfo"]["/Marked"] == True

# It also strictly requires a structural layout root tree pointer
has_structure_tree = "/StructTreeRoot" in catalog

if is_tagged and has_structure_tree:
    print("Success: The PDF contains structural tags.")
else:
    print("No structural tags found. The PDF is not tagged.")
Method 3: Using the Command Line (pdfminer)
If you prefer using terminal utilities, pdfminer (a popular Python PDF extraction package) has a built-in layout debugging command called dumppdf.py.
Run the command with the -T (Tagged mode) flag to print the underlying tag arrangement directly to your terminal screen: [
dumppdf.py -T your_file.pdf  If it contains tags: It dumps an HTML-like layout structural tree layout featuring nodes like <Document>, <H1>, <P>, or <Table>.

If it lacks tags: The terminal returns an empty structure or an execution message indicating that no root structural tag framework was discovered in the file data stream.

Did you like this?
Tip admin with Cryptocurrency

Donate Bitcoin to admin

Scan to Donate Bitcoin to admin
Scan the QR code or copy the address below into your wallet to send some bitcoin:

Donate Bitcoin Cash to admin

Scan to Donate Bitcoin Cash to admin
Scan the QR code or copy the address below into your wallet to send bitcoin:

Donate Ethereum to admin

Scan to Donate Ethereum to admin
Scan the QR code or copy the address below into your wallet to send some Ether:

Donate Litecoin to admin

Scan to Donate Litecoin to admin
Scan the QR code or copy the address below into your wallet to send some Litecoin:

Donate Monero to admin

Scan to Donate Monero to admin
Scan the QR code or copy the address below into your wallet to send some Monero:

Donate ZCash to admin

Scan to Donate ZCash to admin
Scan the QR code or copy the address below into your wallet to send some ZCash:

Leave a Reply