FixMyTakeout

Import a Google Takeout export into PhotoPrism with the dates inside the files

PhotoPrism can read Google's JSON sidecars on its own, but its matcher only finds two file-name patterns, and neither is the one current exports use. Give it a fixed export and it reads the date, place and caption straight from each file, no sidecar needed.

As at 29 September 2026, for the PhotoPrism develop branch and its user guide.

Date PhotoPrism reads firstEXIF DateTimeOriginal
No date inside the fileDate in the name or path, then ModifyDate, then file modified time
CaptionsDescription, ImageDescription, Caption, Caption-Abstract

Index the folder, or import it

PhotoPrism offers two ways in. Indexing reads files where they are, inside the originals directory, and leaves names and folders alone. Importing copies or moves files from the import directory into originals, renames them with new unique names and sorts them into year and month folders. The user guide says most people with an existing library will want to index their originals directly, and a fixed export is exactly that: the folders are already organized by year and album.

  1. Fix the export with FixMyTakeout and unzip every fixmytakeout-part- zip into a folder inside your originals directory, for example originals/takeout-fixed.
  2. In PhotoPrism, open Library > Index.
  3. Pick the takeout-fixed folder and click Start.

To import instead, unzip into the import directory, open Library > Import, tick Move Files if you do not want a second copy left behind, and click Import. Uploading through the web interface goes through a temporary folder and is then imported the same way; WebDAV is also supported for copying files across.

From the PhotoPrism user guide: Originals, Import and Upload.

What PhotoPrism reads from Google's JSON, and which names it finds

The migration page in PhotoPrism's guide says to extract a Takeout archive into originals, or import it, alongside the JSON files. Its Google JSON parser (internal/meta/json_gphotos.go) takes five things from a sidecar: title, description (which becomes the caption), photoTakenTime (which becomes the capture time), geoData latitude, longitude and altitude (not geoDataExif), and imageViews. Two rules limit how much of that reaches a current export:

  • The sidecar lookup in pkg/fs/file_type.go (FindAll) only tries name.ext.json and basename.json. Since about October 2024, Takeout names its sidecars name.ext.supplemental-metadata.json, cut to 51 characters when longer, so 20161105_170829.jpg.supplemental-metadata.json and PXL_20240817_202602411.mp4.supplemental-metada.json are never opened. There is no handling of the suffix in the source.
  • JSON values only fill fields the embedded EXIF left empty. A photo that already carries a date keeps it whatever the JSON says.

Two smaller points. The user guide lists "Date/Time Created/Updated" among the fields read, but the code parses creationTime and modificationTime and never uses them. And albums are not imported from Takeout; the album folders simply become folders.

Migrating from Google Photos in the user guide; json_gphotos.go on GitHub.

Which date PhotoPrism uses

The EXIF pass reads the first of these tags that holds a date, and the ExifTool pass adds the sub-second variants plus CreationTime and CreationDate. For videos it also looks at CreationDate, MediaCreateDate and TrackCreateDate.

OrderTag PhotoPrism readsWritten by FixMyTakeout
1DateTimeOriginalYes, photos
2DateTimeCreatedNot needed
3CreateDateYes, photos and videos
4DateTimeNot needed
5DateTimeDigitizedNot needed
VideosCreationDate, MediaCreateDate, TrackCreateDateYes, all three

When no tag yields a date, TakenAt in internal/photoprism/mediafile.go falls through this list: a date in the file name or path, then EXIF ModifyDate, then the file's modification time, then the current time. A fixed export rarely gets past the first row, and a file that had no date anywhere still lands on the right day through its modified time, provided you unzip with a tool that keeps it.

Tag order from the EXIF developer guide; fallback order from mediafile.go in the PhotoPrism repository.

Location, captions and XMP sidecars

Position comes from GPSPosition or the GPSLatitude and GPSLongitude pair, which FixMyTakeout writes whenever the file has no location of its own and Google recorded a real one. Captions are read from Description, ImageDescription, Caption or Caption-Abstract; a fixed export fills the first two.

An XMP sidecar next to a file takes priority over the embedded values, including GPS. FixMyTakeout writes into the files and creates no sidecars, so nothing overrides what it wrote. If you have XMP files from another tool in the same folder, they win.

Metadata in the user guide and the XMP developer guide.

Leave the JSON files out

With a fixed export the date, place and caption are already inside each file, and PhotoPrism only consults the JSON for fields that are empty. Keeping the sidecars adds thousands of small files to originals for no gain, and the few it can match (older name.ext.json names) would only ever fill a blank. Copy the photo and video folders across and skip the .json files; FixMyTakeout's output zips contain only the media, so this happens by default.

Takeout repeats a photo in its year folder and in every album folder. If you want one copy per photo on disk, tick the option to leave out album-folder copies before running the fix; it drops an album copy only when a file with the same name and size sits in a year folder.

Check the result

  1. Open a photo's details in PhotoPrism. The capture date and the coordinates should match what Google Photos showed.
  2. Open a photo you captioned in Google Photos and confirm the caption is there; PhotoPrism reads it from Description or ImageDescription.
  3. Filter fixmytakeout-report.csv for date_source equal to none found. Those files sit at their file date, which is the export date; give them a date by hand in PhotoPrism or leave them.