Takeout JSON

Fix Google Takeout Dates With exiftool: the Honest Guide

The exiftool command that copies dates and GPS from Takeout .json sidecars into your photos, where it breaks, and when to stop and use a GUI.

exiftool is free, runs everywhere, and can fix a Google Takeout export. Most guides give you one command and stop. That command works on about four photos in five. This one tells you what happens to the fifth.

Install it

On a Mac, brew install exiftool. On Debian or Ubuntu, sudo apt install libimage-exiftool-perl. On Fedora, sudo dnf install perl-Image-ExifTool. On Windows, download the zip from exiftool.org, unpack it, and rename exiftool(-k).exe to exiftool.exe. Then open a terminal in the folder that holds your unpacked Takeout folder.

Work on a copy the first time. exiftool writes into your files.

The command

Every photo has a sidecar beside it, IMG_2034.JPG.supplemental-metadata.json in exports from 2024 onward, IMG_2034.JPG.json in older ones. The sidecar's photoTakenTime.timestamp is the real date, in seconds since 1970. This copies it into the photo:

exiftool -r -d %s -tagsfromfile "%d/%F.supplemental-metadata.json" \
  "-DateTimeOriginal<PhotoTakenTimeTimestamp" \
  "-CreateDate<PhotoTakenTimeTimestamp" \
  "-FileModifyDate<PhotoTakenTimeTimestamp" \
  -ext jpg -ext jpeg -ext png -ext heic -ext gif \
  -overwrite_original -progress "Takeout/Google Photos"

Piece by piece: -r walks subfolders. -d %s tells exiftool the date it reads is an epoch number. -tagsfromfile names the sidecar using %d (the photo's folder) and %F (its filename with extension). The three lines with < copy the timestamp into the EXIF date, the EXIF create date, and the file's modified date. -overwrite_original stops exiftool from leaving a _original copy of every file.

For an older export, run it again with "%d/%F.json". Files that already got a date the first time are simply rewritten with the same value.

Add GPS in the same pass with four more lines, if you want it:

  "-GPSLatitude<GeoDataLatitude" "-GPSLatitudeRef<GeoDataLatitude" \
  "-GPSLongitude<GeoDataLongitude" "-GPSLongitudeRef<GeoDataLongitude" \

Google writes 0.0 for photos with no location, so wrap that in -if '$GeoDataLatitude ne 0' or you will put a few hundred photos in the Atlantic. There is more on this in restoring GPS from Takeout.

When it finishes, exiftool prints how many files it updated and how many it skipped. The skipped ones are where the evening goes.

Where it breaks

Truncated sidecar names. Google cuts long sidecar names off at about 46 characters. PXL_20230812_193044123.RAW-01.COVER.jpg gets a sidecar called PXL_20230812_193044123.RAW-01.COVER.supplemen.json or shorter. The %F pattern never matches. Long camera names, WhatsApp names and anything with a description in the filename hit this. You have to list the leftovers and match them by hand or with a script.

Duplicates with (1). If you uploaded the same name twice, the photo is IMG_1234(1).jpg but the sidecar is IMG_1234.jpg(1).json. The bracket moved. A rename pass on the sidecars fixes it before you run the main command:

for j in "Takeout/Google Photos"/*/*"("*").json"; do
  mv "$j" "$(echo "$j" | sed -E 's/\.([a-zA-Z0-9]+)\(([0-9]+)\)(\.supplemental-metadata)?\.json$/(\2).\1\3.json/')"
done

Edited copies. IMG_1234-edited.jpg has no sidecar of its own. It shares the original's. Once the originals are done, copy from them:

for f in "Takeout/Google Photos"/*/*-edited.*; do
  exiftool -tagsfromfile "${f/-edited/}" -AllDates -GPS:all -overwrite_original "$f"
done

Videos. MP4 and MOV files do not use EXIF. They keep their dates in the QuickTime container, in different tags, and those tags are read as UTC:

exiftool -r -d %s -api QuickTimeUTC -tagsfromfile "%d/%F.supplemental-metadata.json" \
  "-CreateDate<PhotoTakenTimeTimestamp" "-ModifyDate<PhotoTakenTimeTimestamp" \
  "-TrackCreateDate<PhotoTakenTimeTimestamp" "-MediaCreateDate<PhotoTakenTimeTimestamp" \
  "-FileModifyDate<PhotoTakenTimeTimestamp" \
  -ext mp4 -ext mov -overwrite_original "Takeout/Google Photos"

Live Photo clips have no sidecar at all, so they stay undated after this. The Live Photo pairs article has a loop for them.

The time zone trap

The sidecar timestamp is an exact instant in UTC. EXIF DateTimeOriginal is a wall-clock time with no zone. exiftool bridges the gap using your computer's current time zone. A photo taken at 11:05 in Paris comes out as 11:05 if your machine is set to Paris and 05:05 if it is set to New York.

Set the zone before you run, for the place most of your photos were taken:

TZ=Europe/Paris exiftool ...

Holiday photos from other zones will still be off by a few hours. There is no way around that from the sidecar alone; the camera's own EXIF, if it survived, is the only record of local time. Do not "fix" photos that already have a good EXIF date. Add -if 'not $DateTimeOriginal' to leave them alone.

Is the evening worth it

For a clean export of a few thousand camera photos, exiftool takes an hour including reading this. Budget an evening for a real library with WhatsApp images, screenshots, (1) duplicates, HEIC, videos and Live Photos, and expect to run exiftool -r -if 'not $DateTimeOriginal' -filename a few times to see what is still undated.

If you also want files renamed by date, sorted into year and month folders, HEIC turned into JPG and Live Photo pairs kept together, you are chaining four more commands and a loop. That is fine if you enjoy it. GooglePhotosTakeoutHelper is a free script that handles the naming quirks for you, and it is a good middle step if you are comfortable with a terminal but do not want to write the sed yourself.

The app

Takeout JSON Metadata Fixer does the whole list in one run, with a dry run first, on macOS, Windows and Linux.

It matches every photo to its sidecar, including the truncated names, the (1) duplicates and the -edited copies, and writes photoTakenTime and GPS into the file. Videos get the QuickTime tags. Live Photo clips inherit the still's date. Photos with no sidecar keep their EXIF date, and photos with neither get the file date, so nothing comes out undated.

Naming and folder templates are optional; "Keep names" and "Keep my folders" does dates only. It checks disk space before it starts and runs entirely offline. The first 500 photos are free. Unlimited is $9.99 once, which is less than an evening.

Frequently asked questions

exiftool says "Warning: No writable tags set from" a sidecar. What does it mean?

The sidecar exists but has no photoTakenTime, or the name pattern matched the wrong file. Open the .json and check. Album metadata.json files trigger this too and can be ignored.

Can I run it on the zips without unpacking?

No. exiftool needs the files on disk. Unpack all parts into one folder first, as described in Takeout split into many zip parts.

Does writing EXIF change the picture?

No. exiftool rewrites the metadata block and leaves the image data untouched. The file may grow by a few hundred bytes.

Which date should I copy, photoTakenTime or creationTime?

photoTakenTime. creationTime is when the file was uploaded to Google, which is often years later.