Snapchat Memories Export to iCloud – The Easy and Free Way

Snapchat has started putting Memories behind a paywall. Users are now limited to 5 GB unless they subscribe. But by following this guide, you can export your Memories to iCloud easily—and completely free.

Steps:

  • In Snapchat, export your Memories and export the JSON files
    • Then click Next to choose your date range
  • Locate the file: memories_history.json
  • Run the script on this page
  • Upload all the JPG files from the directory snapmemoriesJPG to iCloud Photo
  • Upload all the MP4 files from the directory snapmemoriesMP4 to iCloud Drive

Important:
Copy and paste the script into ChatGPT. ChatGPT will verify the script and generate a simple step-by-step guide for you!


#!/usr/bin/env bash

# Linux script for easy and free export of jpg/mp4 from Snapchat Memories to iCloud.
# Versjon 1.8 (C) HS, www.vargbladet.no
#
# Needs:
# Dowload The file memories_history.json from Snapchat.
# -you have to: Export your Memories AND Export JSON Files, then click Next to select daterange (max 1 year at a time)
# Install Ubuntu (free linux www.ubuntu.com) on a used or new laptop.
# -Dependencies in Ubuntu: jq, curl, date, exiftool, unzipm ffmpeg
# -If you want to download memories_history.json in Ubuntu you have to use the browser Chromium.
#
# Result:
# *The jpg files are in the snapmemoriesJPG directory, -ready to be uploaded to iCloud Photo using Firefox.
# *The mp4 files are in the snapmemoriesMP4 directory, -the mp4-files can ONLY be uploaded to iCloud Drive using Firefox.
#
# Start with this:
# Copy and paste the script into ChatGPT to generate a simple step-by-step guide!
#
# ChatGPT-prompt:
# «Explain in a simple way in words what the script does and verify it is safe to use. Then generate a simple step-by-step guide how to download and install Ubuntu completely on a used or new laptop and the dependencies. Then how to make the script executable and how to run it.»
#

set -euo pipefail
# — Make directories —
BASE_DIR=»$(cd «$(dirname «${BASH_SOURCE[0]}»)» && pwd)»
OUT_DIR=»$BASE_DIR/snapmemoriesJPG»
OUT_DIRMP4=»$BASE_DIR/snapmemoriesMP4″
METADATA_DIR=»$BASE_DIR/metadata»
TMP_DIR=»$BASE_DIR/tmp»

echo «Make resultfiles-dir: $OUT_DIR»
mkdir -p «$OUT_DIR»
echo «Make metadata-dir (for info): $METADATA_DIR»
mkdir -p «$METADATA_DIR»
mkdir -p «$TMP_DIR»

JSON_FILE=»$BASE_DIR/memories_history.json»

if [[ ! -f «$JSON_FILE» ]]; then
echo «Error: JSON-file $JSON_FILE does not exists in same directory.»
exit 1
fi

# — Read all «Saved Media» objects in an array —
mapfile -t items < <(jq -c ‘.[«Saved Media»][]’ «$JSON_FILE»)
echo «Found ${#items[@]} elements (jpg/mp4) in JSON. The final result can be less because of duplicates.»

# — Iterat the elements —
for item in «${items[@]}»; do
media_type=$(jq -r ‘.[«Media Type»]’ <<< «$item»)
date_str=$(jq -r ‘.Date’ <<< «$item»)
download_url=$(jq -r ‘.[«Media Download Url»]’ <<< «$item»)

if [[ «$download_url» == «null» || -z «$download_url» ]]; then
continue
fi

media_type_lower=$(echo «$media_type» | tr ‘[:upper:]’ ‘[:lower:]’)
case «$media_type_lower» in
image) ext=».jpg» ;;
video) ext=».mp4″ ;;
*) continue ;;
esac

timestamp=$(date -u -d «$date_str» +»%s»)
filename=$(date -u -d «@$timestamp» +»%Y-%m-%d_%H-%M-%S»)»$ext»
filepath=»$OUT_DIR/$filename»

# Download file if it not exists, skip if not. Result is no duplicates.
if [[ ! -f «$filepath» ]]; then
echo «Downloading $filename…»
if ! curl -sSL «$download_url» -o «$filepath»; then
echo «FYI: Could not download $filename. Skipping it.»
continue
fi
fi

# Check if the file is a ZIP (Snapchat zips sometimes images/videos.)
actual_file=»$filepath»
if file «$filepath» | grep -q ‘Zip archive data’; then
echo «FYI: $filename is a ZIP, unpacking it…»
unzip -o «$filepath» -d «$TMP_DIR»
# Find the first image or video
extracted=$(find «$TMP_DIR» -type f \( -iname ‘*.jpg’ -o -iname ‘*.jpeg’ -o -iname ‘*.mp4’ \) | head -n1)
if [[ -z «$extracted» ]]; then
echo «No valid files in ZIP. Skipping it.»
continue
fi
# Move unpacked files to resultfiles with correct name
mv «$extracted» «$filepath»
# Clean tmp directory
rm -rf «$TMP_DIR»/*
actual_file=»$filepath»
fi

# Set timestamp
if command -v SetFile >/dev/null 2>&1; then
SetFile -d «$(date -u -d «@$timestamp» +»%m/%d/%Y %H:%M:%S»)» «$actual_file»
fi

# Update EXIF/MP4 metadata for correct date in icloud and other photo systems
exif_date=$(date -u -d «@$timestamp» +»%Y:%m:%d %H:%M:%S»)
if [[ «$media_type_lower» == «image» ]]; then
if file «$actual_file» | grep -q ‘JPEG image data’; then
exiftool -overwrite_original \
-DateTimeOriginal=»$exif_date» \
-CreateDate=»$exif_date» \
-ModifyDate=»$exif_date» \
«$actual_file»
else
echo «FYI: $filename is not a valid JPG. Skipping EXIF.»
fi

elif [[ «$media_type_lower» == «video» ]]; then
# Check for valid video formats
set +e # tillat feil fra exiftool
if file «$actual_file» | grep -qiE ‘ISO Media|MP4|Matroska|AVI|QuickTime’; then
exiftool -overwrite_original \
-CreateDate=»$exif_date» \
-TrackCreateDate=»$exif_date» \
-MediaCreateDate=»$exif_date» \
«$actual_file»
else
echo «FYI: $filename is not a valid video file. Skipping EXIF.»
fi
set -e # gjenaktiver feilstopp

# — Convert to iCloud-friendly MP4 format —
echo «Converting $filename to iCloud-friendly MP4…»
converted_file=»${filepath%.mp4}-icloud.mp4″

if ! ffmpeg -y -hide_banner -loglevel error -i «$actual_file» \
-vf «format=yuv420p» \
-c:v libx264 -preset slow -crf 18 \
-c:a aac -b:a 192k \
«$converted_file»; then
echo «FYI: ffmpeg failed on $filename. Skipping conversion.»
continue
fi

mv «$converted_file» «$filepath»
else
echo «FYI: $filename is not a valid. Skipping EXIF.»
fi
# Set the files access and modified time
touch -a -m -d @»$timestamp» «$actual_file»

# Save metadata for the file. This is just for information.
json_filename=»${filename%.*}.json»
json_path=»$METADATA_DIR/$json_filename»
echo «$item» | jq ‘.’ > «$json_path»

done
# Moves all of mp4 from OUT_DIR to OUT_DIRMP4
mkdir -p «$OUT_DIRMP4»
mv «$OUT_DIR»/*.mp4 «$OUT_DIRMP4/» 2>/dev/null || true

# — Remove any 0-byte files —
echo «Removing zero-byte files (if any)…»
find «$OUT_DIR» -type f -size 0 -print -delete
find «$OUT_DIRMP4» -type f -size 0 -print -delete

rm -rf «$METADATA_DIR»
rm -rf «$TMP_DIR»

printf «%b\n» «Finished! All the mediafiles and metadata are downloaded and combined. And all datestamps are correct for iCloud or other photo systems.\n*The jpg files are in the snapmemoriesJPG directory, -ready to be uploaded to iCloud Photo using Firefox.\n*The mp4 files are in the snapmemoriesMP4 directory, -the mp4-files can ONLY be uploaded to iCloud Drive using Firefox because Apple wants it to be difficult…»