Last active
April 4, 2022 11:33
-
-
Save steffenz/7750af0204a23720bdbef1f4f8808739 to your computer and use it in GitHub Desktop.
Download all Snapchat Memories (Node)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
1. Go to https://accounts.snapchat.com/ and request download of your data. | |
2. Download zip-file (when ready) and locate json/memories_history.json | |
3. Create a new folder with this script and the memories_history.json file | |
4. Install node-fetch; npm install node-fetch@^2.6.6 (using older version to avoid having to import as module) | |
5. Run the script. | |
Files will be prefixed with the date and a unique ID (from Snapchat) to avoid overwriting (see more details below). | |
This script was originally inspired by this StackOverflow question (but has since diverged greatly); https://stackoverflow.com/questions/61058637/snapchat-download-all-memories-at-once | |
Now go get those memories before the links expire ;) | |
*/ | |
const fetch = require('node-fetch'); | |
const fs = require('fs'); | |
// Folder to save all files in | |
const saveToFolder = './Memories'; | |
// Helper-function to format numbers under 10 with leading zeros (helps with OCD). | |
const getNumberWithLeadingZero = (number) => number > 9 ? number : `0${number}`; | |
// Stupidly create the date manually (look ma, no library!) | |
const getDate = (date, spacer = '-') => `${date.getFullYear()}${spacer}${getNumberWithLeadingZero(date.getMonth()+1)}${spacer}${getNumberWithLeadingZero(date.getDate())}${spacer}${getNumberWithLeadingZero(date.getHours())}${spacer}${getNumberWithLeadingZero(date.getMinutes())}`; | |
(async () => { | |
// Create output folder if it doesn't exists | |
if(!fs.existsSync(saveToFolder)) { fs.mkdirSync(saveToFolder)} | |
// All memories resides within the "Saved Media" object at the time of writing. | |
const memories = JSON.parse(fs.readFileSync('memories_history.json'))['Saved Media']; | |
for (const memory of memories){ | |
// Create a new Date object of the memory date. | |
const fileDate = new Date(Date.parse(memory['Date'])); | |
// Make a request to get the actual media URL on AWS (slaps on required authentication etc) | |
const fileDownloadURLRequest = await fetch(memory['Download Link'], { method: 'POST' }); | |
// The actual media URL - we'll parse the URL to be able to extract the unique filename. | |
// I did originally just use the date as filename, but if you've recorded multiple snaps at once (typically a video) they will all have the same timestamp and thus be overwritten until the last part .. | |
const fileDownloadUrl = new URL(await fileDownloadURLRequest.text()); | |
// Get the actual data file from AWS | |
const fileContent = await fetch(fileDownloadUrl, { method: 'GET' }); | |
// Last part of the URL contains filename, so let's split the string and pop the last item in the array. | |
const originalFileName = fileDownloadUrl.pathname.split('/').pop(); | |
// Use helper to get pretty date (makes sorting/archiving easier), and slap on unique ID to avoid overwriting. | |
const newFileName = `${getDate(fileDate)}_${originalFileName}`; | |
// Create new file with the correct file name in our desired folder | |
const newFileStream = fs.createWriteStream(`${saveToFolder}/${newFileName}`); | |
// Pipe contents into file | |
fileContent.body.pipe(newFileStream); | |
// Notify when file is saved | |
newFileStream.on('finish', () => console.log(`💾 Saved ${newFileName}`)); | |
// Print out errors (might need to be further improved if you experience errors) | |
newFileStream.on('error', (err) => console.error(err)); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment