Scraper - Instagram
Instagram menjadi salah satu platform media sosial terpopuler dengan miliaran pengguna aktif setiap bulannya.

Muhamad Nur Ibad
24 Januari 2025•1 menit baca

Membuat Scraper Instagram Downloader Menggunakan Node.js
Instagram menjadi salah satu platform media sosial terpopuler dengan miliaran pengguna aktif setiap bulannya. Banyak pengguna sering kali ingin mengunduh konten dari Instagram, seperti foto, video, Reels, atau Stories, untuk keperluan pribadi. Namun, Instagram tidak menyediakan fitur bawaan untuk mengunduh konten ini. Oleh karena itu, kita dapat membuat scraper Instagram downloader menggunakan Node.js untuk memenuhi kebutuhan ini.
Mengenal Scraper Instagram Downloader
Scraper Instagram downloader adalah alat otomatis yang memungkinkan Anda untuk mendapatkan tautan unduhan dari konten Instagram. Dengan bantuan pustaka seperti axios dan cheerio, kita dapat mengambil data dari Instagram dan memprosesnya agar siap diunduh.
Alat dan Pustaka yang Digunakan
1. Axios: Untuk melakukan permintaan HTTP dan mendapatkan data dari API Instagram atau situs pihak ketiga.
2. Cheerio: Untuk memproses dan menavigasi konten HTML.
3. qs: Untuk mengubah objek JavaScript menjadi string format x-www-form-urlencoded.
Langkah-Langkah Implementasi
1. Mengambil Data Post Instagram
Pertama, kita perlu mengekstrak ID konten Instagram dari URL menggunakan regex. ID ini akan digunakan untuk mengambil data lengkap dari API Instagram.
function getInstagramPostId(url) {
const regex = /(?:https?:\/\/)?(?:www\.)?instagram\.com\/(?:p|tv|stories|reel)\/([^/?#&]+).*/;
const match = url.match(regex);
return match ? match[1] : null;
}
2. Mengirim Permintaan ke API Instagram
Setelah mendapatkan ID konten, kita dapat mengirim permintaan ke API Instagram menggunakan GraphQL untuk mendapatkan detail media (URL gambar/video, jumlah likes, komentar, dll.).
async function getPostGraphqlData(postId, proxy) {
const encodedData = encodeGraphqlRequestData(postId);
const response = await axios.post(
"https://www.instagram.com/api/graphql",
encodedData, {
headers: HEADERS,
httpsAgent: proxy
},
);
return response.data;
}
3. Mengekstrak Informasi Media
Data yang diterima dari API biasanya berupa objek JSON besar. Kita hanya perlu mengambil informasi penting seperti tautan gambar/video, username, caption, jumlah likes, dan komentar.
function extractPostInfo(mediaData) {
const getUrlFromData = (data) => {
if (data.edge_sidecar_to_children) {
return data.edge_sidecar_to_children.edges.map(
(edge) => edge.node.video_url || edge.node.display_url,
);
}
return data.video_url ? [data.video_url] : [data.display_url];
};
return {
url: getUrlFromData(mediaData),
metadata: {
caption: mediaData.edge_media_to_caption.edges[0]?.node.text || null,
username: mediaData.owner.username,
like: mediaData.edge_media_preview_like.count,
comment: mediaData.edge_media_to_comment.count,
isVideo: mediaData.is_video,
},
};
}
4. Menggunakan Situs Pihak Ketiga
Jika API Instagram gagal memberikan data (misalnya karena pembatasan), kita dapat menggunakan situs pihak ketiga seperti Snapsave. Dengan mengirim permintaan ke server mereka, kita bisa mendapatkan tautan unduhan.
const getDownloadLinks = (url) => {
return new Promise(async (resolve, reject) => {
try {
const response = await axios.post(
"https://snapsave.app/action.php?lang=id",
"url=" + url, {
headers: {
"content-type": "application/x-www-form-urlencoded",
referer: "https://snapsave.app/id",
},
},
);
const data = response.data;
const videoPageContent = getVideoUrl(data);
const $ = cheerio.load(videoPageContent);
const downloadLinks = [];
$("div.download-items__btn").each((btnIndex, button) => {
let downloadUrl = $(button).find("a").attr("href");
if (!/https?:\/\//.test(downloadUrl || "")) {
downloadUrl = "https://snapsave.app" + downloadUrl;
}
downloadLinks.push(downloadUrl);
});
return resolve({
url: downloadLinks,
});
} catch (error) {
return reject({ msg: error.message });
}
});
};
5. Fitur Utama: Instagram Downloader
Kita menyusun logika utama agar dapat mencoba berbagai metode untuk mendapatkan data. Jika API Instagram gagal, maka sistem akan mencoba menggunakan situs pihak ketiga.
async function Instagram(url) {
let result = "";
try {
result = await ig(url); // Mengambil data dari API Instagram
} catch (e) {
try {
result = await getDownloadLinks(url); // Menggunakan situs pihak ketiga
} catch (e) {
result = { msg: "Try again later" };
}
}
return result;
}
Code Lengkapnya
Berikut adalah kode lengkap dari scraper instagram
const axios = require("axios");
const cheerio = require("cheerio");
const qs = require("qs");
const getDownloadLinks = (url) => {
return new Promise(async (resolve, reject) => {
try {
if (
!url.match(
/(?:https?:\/\/(web\.|www\.|m\.)?(facebook|fb)\.(com|watch)\S+)?$/,
) &&
!url.match(/(https|http):\/\/www.instagram.com\/(p|reel|tv|stories)/gi)
) {
return reject({
msg: "Invalid URL",
});
}
function decodeData(data) {
let [part1, part2, part3, part4, part5, part6] = data;
function decodeSegment(segment, base, length) {
const charSet =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/".split(
"",
);
let baseSet = charSet.slice(0, base);
let decodeSet = charSet.slice(0, length);
let decodedValue = segment
.split("")
.reverse()
.reduce((accum, char, index) => {
if (baseSet.indexOf(char) !== -1) {
return (accum += baseSet.indexOf(char) * Math.pow(base, index));
}
}, 0);
let result = "";
while (decodedValue > 0) {
result = decodeSet[decodedValue % length] + result;
decodedValue = Math.floor(decodedValue / length);
}
return result || "0";
}
part6 = "";
for (let i = 0, len = part1.length; i < len; i++) {
let segment = "";
while (part1[i] !== part3[part5]) {
segment += part1[i];
i++;
}
for (let j = 0; j < part3.length; j++) {
segment = segment.replace(new RegExp(part3[j], "g"), j.toString());
}
part6 += String.fromCharCode(
decodeSegment(segment, part5, 10) - part4,
);
}
return decodeURIComponent(encodeURIComponent(part6));
}
function extractParams(data) {
return data
.split("decodeURIComponent(escape(r))}(")[1]
.split("))")[0]
.split(",")
.map((item) => item.replace(/"/g, "").trim());
}
function extractDownloadUrl(data) {
return data
.split('getElementById("download-section").innerHTML = "')[1]
.split('"; document.getElementById("inputData").remove(); ')[0]
.replace(/\\(\\)?/g, "");
}
function getVideoUrl(data) {
return extractDownloadUrl(decodeData(extractParams(data)));
}
const response = await axios.post(
"https://snapsave.app/action.php?lang=id",
"url=" + url, {
headers: {
accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"content-type": "application/x-www-form-urlencoded",
origin: "https://snapsave.app",
referer: "https://snapsave.app/id",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
},
},
);
const data = response.data;
const videoPageContent = getVideoUrl(data);
const $ = cheerio.load(videoPageContent);
const downloadLinks = [];
$("div.download-items__thumb").each((index, item) => {
$("div.download-items__btn").each((btnIndex, button) => {
let downloadUrl = $(button).find("a").attr("href");
if (!/https?:\/\//.test(downloadUrl || "")) {
downloadUrl = "https://snapsave.app" + downloadUrl;
}
downloadLinks.push(downloadUrl);
});
});
if (!downloadLinks.length) {
return reject({
msg: "No data found",
});
}
return resolve({
url: downloadLinks,
metadata: {
url: url,
},
});
} catch (error) {
return reject({
msg: error.message,
});
}
});
};
const HEADERS = {
Accept: "*/*",
"Accept-Language": "en-US,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded",
"X-FB-Friendly-Name": "PolarisPostActionLoadPostQueryQuery",
"X-CSRFToken": "RVDUooU5MYsBbS1CNN3CzVAuEP8oHB52",
"X-IG-App-ID": "1217981644879628",
"X-FB-LSD": "AVqbxe3J_YA",
"X-ASBD-ID": "129477",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.2 Chrome/87.0.4280.141 Mobile Safari/537.36",
};
function getInstagramPostId(url) {
const regex =
/(?:https?:\/\/)?(?:www\.)?instagram\.com\/(?:p|tv|stories|reel)\/([^/?#&]+).*/;
const match = url.match(regex);
return match ? match[1] : null;
}
function encodeGraphqlRequestData(shortcode) {
const requestData = {
av: "0",
__d: "www",
__user: "0",
__a: "1",
__req: "3",
__hs: "19624.HYP:instagram_web_pkg.2.1..0.0",
dpr: "3",
__ccg: "UNKNOWN",
__rev: "1008824440",
__s: "xf44ne:zhh75g:xr51e7",
__hsi: "7282217488877343271",
__dyn: "7xeUmwlEnwn8K2WnFw9-2i5U4e0yoW3q32360CEbo1nEhw2nVE4W0om78b87C0yE5ufz81s8hwGwQwoEcE7O2l0Fwqo31w9a9x-0z8-U2zxe2GewGwso88cobEaU2eUlwhEe87q7-0iK2S3qazo7u1xwIw8O321LwTwKG1pg661pwr86C1mwraCg",
__csr: "gZ3yFmJkillQvV6ybimnG8AmhqujGbLADgjyEOWz49z9XDlAXBJpC7Wy-vQTSvUGWGh5u8KibG44dBiigrgjDxGjU0150Q0848azk48N09C02IR0go4SaR70r8owyg9pU0V23hwiA0LQczA48S0f-x-27o05NG0fkw",
__comet_req: "7",
lsd: "AVqbxe3J_YA",
jazoest: "2957",
__spin_r: "1008824440",
__spin_b: "trunk",
__spin_t: "1695523385",
fb_api_caller_class: "RelayModern",
fb_api_req_friendly_name: "PolarisPostActionLoadPostQueryQuery",
variables: JSON.stringify({
shortcode: shortcode,
fetch_comment_count: null,
fetch_related_profile_media_count: null,
parent_comment_count: null,
child_comment_count: null,
fetch_like_count: null,
fetch_tagged_user_count: null,
fetch_preview_comment_count: null,
has_threaded_comments: false,
hoisted_comment_id: null,
hoisted_reply_id: null,
}),
server_timestamps: "true",
doc_id: "10015901848480474",
};
return qs.stringify(requestData);
}
async function getPostGraphqlData(postId, proxy) {
try {
const encodedData = encodeGraphqlRequestData(postId);
const response = await axios.post(
"https://www.instagram.com/api/graphql",
encodedData, {
headers: HEADERS,
httpsAgent: proxy
},
);
return response.data;
} catch (error) {
throw error;
}
}
function extractPostInfo(mediaData) {
try {
const getUrlFromData = (data) => {
if (data.edge_sidecar_to_children) {
return data.edge_sidecar_to_children.edges.map(
(edge) => edge.node.video_url || edge.node.display_url,
);
}
return data.video_url ? [data.video_url] : [data.display_url];
};
return {
url: getUrlFromData(mediaData),
metadata: {
caption: mediaData.edge_media_to_caption.edges[0]?.node.text || null,
username: mediaData.owner.username,
like: mediaData.edge_media_preview_like.count,
comment: mediaData.edge_media_to_comment.count,
isVideo: mediaData.is_video,
},
};
} catch (error) {
throw error;
}
}
async function ig(url, proxy = null) {
const postId = getInstagramPostId(url);
if (!postId) {
throw new Error("Invalid Instagram URL");
}
const data = await getPostGraphqlData(postId, proxy);
const mediaData = data.data?.xdt_shortcode_media;
return extractPostInfo(mediaData);
}
async function Instagram(url) {
let result = "";
try {
result = await ig(url);
} catch (e) {
try {
result = await getDownloadLinks(url);
} catch (e) {
result = {
msg: "Try again later",
};
}
}
return result;
}
module.exports = Instagram;
Kesimpulan
Dengan scraper Instagram downloader, Anda dapat dengan mudah mendapatkan tautan unduhan konten Instagram untuk berbagai kebutuhan. Pastikan untuk menggunakan alat ini secara bijak dan sesuai hukum, karena mengunduh konten tanpa izin dapat melanggar hak cipta. Implementasi ini menunjukkan bagaimana teknologi modern seperti Node.js, axios, dan cheerio dapat digunakan untuk membangun alat yang kuat dan fleksibel.
Sumber: https://github.com/AxellNetwork/NekoBot/blob/master/scrapers/src/Instagram.js