Skip to content

Instantly share code, notes, and snippets.

@drewbaker
Last active July 2, 2022 06:26
Show Gist options
  • Save drewbaker/0bee04c78b20c3ae5a5a49161b307150 to your computer and use it in GitHub Desktop.
Save drewbaker/0bee04c78b20c3ae5a5a49161b307150 to your computer and use it in GitHub Desktop.
A bookmarklet to download all images from a user on Instagram
/*
* Bookmarklet to download all IG images for the current account page.
* Use https://katanya.co.uk/labs/bookmarklet-generator to generate the bookmarklet.
*
* SEE: https://www.instagram.com/web/search/topsearch/?query=casetify
* SEE: https://www.instagram.com/graphql/query/?query_id=17888483320059182&variables={"id":"6662673","first":50,after:"QVFEaEJRR0tiTXpVUVV5ZVlfQktDUFJYNUpRWlhOMktKbWZXWEh4cHNCSFV2ZDA5RVBaUzFfWmxVOWlaMHNfVU1wNTQ1dFVXZlVoT05oUzRVVHYyNVBZMQ=="}
*/
(async function () {
let userId = "";
let imageUrls = [];
let cursor = "";
// Get the user's ID
const getUserId = async () => {
// Try to get username from the page
let username = document.title.match(/@(.+?)\b/);
if (username && username[1]) {
username = username[1];
}
// No username found on page, so ask for it
if (!username) {
username = prompt("Enter username (you must be on instagram.com):");
}
// Serach IG for the username
const response = await fetch(
`https://www.instagram.com/web/search/topsearch/?query=${username}`,
{ mode: "cors" }
);
const data = await response.json();
// Get the user's ID
userId = data.users[0].user.pk;
};
// Using the IG GQL API, get the user's image URLs
const getImageUrls = async (cursor = "") => {
const vars = {
id: userId,
first: 50,
after: cursor,
};
const response = await fetch(
`https://www.instagram.com/graphql/query/?query_id=17888483320059182&variables=${JSON.stringify(
vars
)}`,
{
mode: "cors",
}
);
const data = await response.json();
const media = data.data.user.edge_owner_to_timeline_media;
// Get any new image URL
media.edges.forEach((edge) => {
imageUrls.push(edge.node.display_url);
});
// If more pages, loop back around
if (media.page_info.has_next_page) {
cursor = media.page_info.end_cursor;
} else {
cursor = false;
}
return cursor;
};
// Download the image
function forceDownload(blob, filename) {
var a = document.createElement("a");
a.download = filename;
a.href = blob;
a.click();
}
// Current blob size limit is around 500MB for browsers
async function downloadResource(url, filename) {
if (!filename) filename = url.split("\\").pop().split("/").pop();
try {
const response = await fetch(url, {
headers: new Headers({
Origin: location.origin,
}),
mode: "cors",
});
const blob = await response.blob();
let blobUrl = window.URL.createObjectURL(blob);
forceDownload(blobUrl, filename);
} catch (e) {
console.error(e);
}
}
console.log("Downloading images...");
// Get the user's ID
await getUserId();
// Get as many images as requested
let amount = prompt("How many images to download?");
amount = parseInt(amount);
cursor = await getImageUrls();
while (cursor) {
if (imageUrls.length > amount) {
break;
}
cursor = await getImageUrls(cursor);
}
// Trim the found amount to match requested amount (as we will be loading pages of images above)
imageUrls = imageUrls.slice(0, amount);
// Log out total found
console.log(
`${imageUrls.length} images found, downloading them all now...`
);
// Now download all images
try {
imageUrls.forEach(function (url) {
downloadResource(url);
});
} catch (e) {
alert("Download failed.");
console.log("Download failed.", e);
}
console.log("Finished!");
}.call(window));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment