Fix EXIF Data on Google Photos Exports

Google Photos does not save date/time changes, descriptions, or GPS edits made in the app back to the photos’ EXIF data. When you export via Google Takeout, that metadata arrives as separate JSON sidecar files (one per photo) instead of being embedded as XMP. Re-importing elsewhere (iCloud, a self-hosted library, etc.) without merging the sidecars silently loses every edit.

ExifTool can merge the JSON sidecar data back into the exported images:

exiftool -r -d %s \
         -tagsfromfile "%d/%F.json" \
                       "-GPSAltitude<GeoDataAltitude" \
                       "-GPSLatitude<GeoDataLatitude" \
                       "-GPSLatitudeRef<GeoDataLatitude" \
                       "-GPSLongitude<GeoDataLongitude" \
                       "-GPSLongitudeRef<GeoDataLongitude" \
                       "-Keywords<Tags" \
                       "-Subject<Tags" \
                       "-Caption-Abstract<Description" \
                       "-ImageDescription<Description" \
                       "-DateTimeOriginal<PhotoTakenTimeTimestamp" \
         -ext "*" -overwrite_original -progress \
         --ext json $GOOGLE_PHOTOS_DIR

How it works:

  • -r recurses through the export directory.
  • -tagsfromfile "%d/%F.json" tells ExifTool to read metadata from the sidecar JSON sitting next to each image.
  • Each "-TAG<JsonField" line copies one JSON field into the corresponding EXIF tag.
  • --ext json excludes the JSON files themselves from being processed as images (the double-dash negates the previous -ext "*").
  • -overwrite_original skips the _original backup files (drop it if you want backups).

Pre-1970 photos

This fails for any photo with a timestamp before 1970, because the JSON stores those as negative Unix timestamps and ExifTool’s date parser rejects them. For those photos, replace the DateTimeOriginal line with the pre-formatted string variant:

"-DateTimeOriginal<PhotoTakenTimeFormatted" -d "%b %d, %Y, %I:%M:%S %p UTC"

Sources

Related: ffmpeg, exiftool