Writing

This guide demonstrates how to write EXIF metadata to image files using tagkit.

CLI

Writing tag values via the CLI is not yet supported.

API

Writing Single Tags

Use the write_tag method to write a single tag to an image. You can specify the tag by name or integer ID, along with its value. If the tag does not exist, it will be created. You may specify an explicit IFD (Image File Directory) using the ifd argument. If not specified, the IFD is determined based on the tag name or ID. For tags associated with both the main and thumbnail IFDs, the main IFD is used by default unless the thumbnail argument is set to True. If the tag already exists, it will be updated with the new value.

If a tag id or tag name is provided that is present in both the main and thumbnail IFDs, the tag will be written to the main IFD only unless you specify ifd='IFD1'. If a tag id or tag name is provided that is present in two other IFDs and the ifd is not specified, the tag will be written to the first IFD that contains the tag and a warning is emitted. IFD’s are searched in the order of IFD0, Exif, GPS, Interop. In general, there is much less chance of overlap when specifying tags by name rather than by ID, but explicitly specifying the IFD eliminates this issue.

Note: Changes are not saved to disk until you call the save() method.

from tagkit.image.exif import ExifImage

# Create an instance for an image
exif = ExifImage("image1.jpg")

# Set a single tag (in-memory)
exif.write_tag("Artist", "Jane Doe")
print(f"Artist tag set for {exif.file_path}")

# Tag 271 is the ID for Make
exif.write_tag(271, "Canon")
print(f"Make tag set for {exif.file_path}")

# Save changes to disk
exif.save()
print(f"Tags written to {exif.file_path}")

Writing Multiple Tags at Once

To efficiently set several tags in a single call, use the write_tags method, which accepts a dictionary of tag names or IDs to values.

from tagkit.image.exif import ExifImage

# Create an instance
exif = ExifImage("image1.jpg")

# Write multiple tags (in-memory)
tags_to_write = {
    "Artist": "Jane Doe",
    "Copyright": "© 2025 Jane Doe"
}
exif.write_tags(tags_to_write)

# Save changes
exif.save()
print(f"Tags written to {exif.file_path}")

Deleting Tags

To remove tags from an image, use the delete_tag method. You can specify the tag by name or ID, and optionally target a specific IFD (via the ifd argument). If the tag exists in both the main and thumbnail IFDs and ifd is not specified, it will be removed from the main IFD only.

You can also delete multiple tags at once using delete_tags, which takes a list of tag names or IDs.

Remember: Call save() to persist deletions to disk.

from tagkit.image.exif import ExifImage

# Create an instance
exif = ExifImage("image1.jpg")

# Get all tags
all_tags = exif.tags

# List of tags to keep
tags_to_keep = ["Make", "Model", "DateTimeOriginal"]

# Remove tags not in the keep list
for tag_name, tag in list(all_tags.items()):
    if tag_name not in tags_to_keep:
        try:
            exif.delete_tag(tag.id, ifd=tag.ifd)
        except KeyError:
            pass  # Tag might already be gone

# Add new tags
exif.write_tag("Artist", "Jane Doe")

# Remove multiple tags at once
exif.delete_tags(["Artist", "Copyright"])

# Save changes
exif.save()
print("Tags updated successfully")

Creating Backups Before Saving

A backup can be created automatically before saving changes to the image file. This helps prevent data loss in case of errors during writing. To enable this feature, pass create_backup=True to the save() method. The backup will be saved with the same name as the original file, but with a .bak extension.

from tagkit.image.exif import ExifImage

# Create an instance
exif = ExifImage("image1.jpg")

# Write tags (in-memory)
tags_to_write = {"Artist": "Jane Doe"}
exif.write_tags(tags_to_write)

# Save changes and create a backup
exif.save(create_backup=True)
print(f"Tags written to {exif.file_path}")
print(f"Backup created at {exif.file_path}.bak")

Writing GPS Information

You can add GPS coordinates to an image as follows:

from tagkit.image.exif import ExifImage

# Create an instance for the image
exif = ExifImage("image1.jpg")

# GPS coordinates (latitude, longitude)
# Latitude and longitude must be provided as tuples of (degrees, minutes, seconds),
# where each value is a (numerator, denominator) tuple (i.e., rational number)
latitude = ((40, 1), (44, 1), (52, 1))   # 40° 44' 52" N
longitude = ((73, 1), (59, 1), (2, 1))   # 73° 59' 2" W

# Set GPS tags (in-memory)
exif.write_tag("GPSLatitude", latitude)
exif.write_tag("GPSLatitudeRef", "N")
exif.write_tag("GPSLongitude", longitude)
exif.write_tag("GPSLongitudeRef", "W")
exif.write_tag("GPSAltitude", (105, 10))      # Altitude in meters as rational (e.g., 10.5m)
exif.write_tag("GPSAltitudeRef", 0)      # 0 = above sea level, 1 = below sea level

# Save changes
exif.save()
print("GPS information added successfully")

Error Handling

Tagkit defines several custom exceptions. Here is an example of handling errors when writing tags:

from tagkit.image.exif import ExifImage
from tagkit.core.exceptions import TagkitError

try:
    exif = ExifImage("path/to/your/image.jpg")
    exif.write_tag("Artist", "Jane Doe")
    exif.save()
    print("Tags written successfully")
except FileNotFoundError:
    print("Error: Image file not found")
except PermissionError:
    print("Error: No permission to write to the file")
except TagkitError as e:
    print(f"Error writing EXIF data: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")