Batch Update Font Metadata Using FontForge

Yes, you can automate metadata updates across multiple font files using FontForge's built-in Python scripting engine. This guide explains how to programmatically batch-process font files to update key metadata fields—such as family names, copyright notices, version strings, and designer credits—without manually opening each file in the FontForge graphical user interface.

How Automation Works in FontForge

FontForge includes a powerful Python extension that provides access to its core font-manipulation engine. When you install FontForge, it typically provides a standalone command-line interpreter executable via fontforge -script <your_script.py>. This allows you to iterate over directories of TrueType (.ttf), OpenType (.otf), or Web Open Font Format (.woff/.woff2) files, apply metadata updates, and re-export the files automatically.

Writing the Batch Metadata Update Script

Below is a complete, minimal Python script that traverses a directory of fonts, modifies their naming and metadata attributes, and generates updated files.

Save the following code as update_metadata.py:

import os
import sys
import fontforge

# Directory containing the fonts to update
INPUT_DIR = "./fonts"
OUTPUT_DIR = "./fonts_updated"

# New metadata values to apply
NEW_COPYRIGHT = "Copyright (c) 2026 Example Foundry. All rights reserved."
NEW_DESIGNER = "Jane Doe"
NEW_VERSION = "2.000"
FAMILY_PREFIX = "Custom "

def process_fonts():
    if not os.path.exists(OUTPUT_DIR):
        os.makedirs(OUTPUT_DIR)

    for filename in os.listdir(INPUT_DIR):
        if filename.lower().endswith((".ttf", ".otf")):
            input_path = os.path.join(INPUT_DIR, filename)
            output_path = os.path.join(OUTPUT_DIR, filename)

            print(f"Processing: {filename}")
            
            # Open the font file
            font = fontforge.open(input_path)

            # Update primary metadata properties
            font.copyright = NEW_COPYRIGHT
            font.version = NEW_VERSION
            
            # Update naming records
            font.familyname = FAMILY_PREFIX + font.familyname
            font.fontname = FAMILY_PREFIX.replace(" ", "") + font.fontname
            font.fullname = FAMILY_PREFIX + font.fullname

            # Update OpenType (SFNT) Name Table values
            # Language ID 0x409 represents English (US)
            # Name ID 9 = Designer, Name ID 0 = Copyright
            font.appendSFNTName("English (US)", "Designer", NEW_DESIGNER)
            font.appendSFNTName("English (US)", "Copyright", NEW_COPYRIGHT)
            font.appendSFNTName("English (US)", "Version", f"Version {NEW_VERSION}")

            # Generate the new font file
            font.generate(output_path)
            font.close()

    print("Batch processing complete.")

if __name__ == "__main__":
    process_fonts()

Essential FontForge Metadata Properties

When modifying font records in Python, FontForge exposes several core attributes directly on the font object:

  • font.fontname: The PostScript name of the font. It should contain no spaces.
  • font.familyname: The family name displayed in font menus (e.g., "Helvetica").
  • font.fullname: The full display name (e.g., "Helvetica Bold").
  • font.weight: The weight description (e.g., "Regular", "Bold", "Light").
  • font.version: The font version string.
  • font.copyright: The high-level copyright declaration.

For deeper OpenType table modifications, use the appendSFNTName(language, string_type, value) method. This handles specific standard table fields such as Manufacturer (Name ID 8), Designer (Name ID 9), URL Vendor (Name ID 11), and License Description (Name ID 13).

Running the Automation Script

Execute the script using the FontForge command-line interface:

fontforge -script update_metadata.py

If your system's default Python environment has the fontforge module properly linked or compiled, you can also run the script directly using standard Python:

python3 update_metadata.py

Best Practices

  • Always work on copies: Never run metadata batch scripts directly on your original source files. Output the modified fonts to a dedicated folder to avoid irreversible corruption.
  • Validate the PostScript name: Ensure that font.fontname does not contain spaces or non-ASCII characters, as invalid PostScript names can cause operating systems or PDF generators to reject the font.
  • Preserve font features: Using font.generate() retains existing hinting, kerning, and OpenType layout features by default, but you should verify your exported fonts in a font validator to ensure all tables remain intact after processing.