🚀 Tutorial Instagram Downloader Pakai Termux (Auto Timestamp & No Overwrite!)
Buat kamu yang aktif banget di Instagram dan pengen punya arsip konten sendiri (reels, foto, story, atau hashtag), kali ini kita bakal bahas cara bikin Instagram downloader pakai Termux yang super rapi dan anti overwrite 🔥
Tutorial ini cocok buat Millennial & Gen Z yang suka ngoprek dikit tapi pengen hasil clean, otomatis, dan profesional 😎
Keyword penting hari ini: termux & instagram downloader.
📱 Kenapa Pakai Termux?
Buat yang belum tahu, Termux adalah aplikasi terminal emulator Android yang bikin HP kamu bisa jalanin perintah Linux.
Dengan termux, kamu bisa:
Install Python
Install library kayak instaloader
Jalanin script instagram downloader langsung dari HP
Simpan hasil ke penyimpanan internal (/sdcard)
Simple tapi powerful banget 💪
⚙️ Step 1 – Install & Setup Termux
Buka Termux lalu jalankan:
pkg update && pkg upgrade -y
pkg install python -y
pip install instaloader
termux-setup-storage
Kenapa termux-setup-storage penting?
Supaya script bisa akses folder /sdcard/ buat simpan hasil download.
🧠 Konsep Script Instagram Downloader Ultra v2.1
Script ini punya beberapa fitur keren:
✅ Login & session
✅ Download single post
✅ Download profile (bulk)
✅ Download story
✅ Download hashtag
✅ Auto rename pakai timestamp
✅ Auto-numbering anti overwrite
✅ Bisa pindah ke internal storage
Format nama file otomatis:
YYYYMMDD_HHMMSS_username_001.jpg
Contoh:
20250221_143052_johndoe_001.jpg 20250221_143052_johndoe_002.jpg 20250221_143053_johndoe_001.mp4
✨ Jadi:
Setiap file punya timestamp unik
Tidak ada file tertimpa
Mudah disortir berdasarkan waktu download
📂 Struktur Folder Hasil Download
downloads/
└── johndoe/
├── 20250221_143052_johndoe_001.jpg
├── 20250221_143052_johndoe_002.jpg
├── 20250221_143053_johndoe_001.mp4
Clean, rapi, dan profesional banget buat arsip konten 🔥
📝 Cara Menjalankan Script
1️⃣ Buat file baru:
nano ig_ultra.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
INSTAGRAM DOWNLOADER ULTRA v2.1
Author: Assistant
Version: 2.1
Features: Login, Session, Single Post, Profile Bulk, Story, Hashtag, File Manager
+ Timestamp Naming + Auto-Numbering Duplicate Files
"""
import os
import sys
import json
import time
import shutil
import getpass
import re
from pathlib import Path
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor, as_completed
try:
import instaloader
from instaloader import Instaloader, Post, Profile, StoryItem, Hashtag
except ImportError:
print("Installing required package: instaloader...")
os.system(f"{sys.executable} -m pip install instaloader")
import instaloader
from instaloader import Instaloader, Post, Profile, StoryItem, Hashtag
class InstagramDownloaderUltra:
def __init__(self):
self.loader = Instaloader(
dirname_pattern='downloads/{target}',
filename_pattern='{date_utc:%Y%m%d}_{shortcode}', # Default, akan di-override
download_pictures=True,
download_videos=True,
download_video_thumbnails=True,
download_geotags=False,
download_comments=False,
save_metadata=True,
compress_json=False,
post_metadata_txt_pattern=''
)
self.session_file = "session-instaloader.json"
self.config_file = "config.json"
self.download_dir = "downloads"
self.internal_dir = "/sdcard/InstagramDownloads"
self.current_user = None
self.download_counter = {} # Track filename counts
self.ensure_directories()
self.load_config()
def ensure_directories(self):
"""Create necessary directories"""
Path(self.download_dir).mkdir(exist_ok=True)
Path("sessions").mkdir(exist_ok=True)
def load_config(self):
"""Load configuration"""
if os.path.exists(self.config_file):
try:
with open(self.config_file, 'r') as f:
config = json.load(f)
self.internal_dir = config.get('internal_dir', self.internal_dir)
except:
pass
def save_config(self):
"""Save configuration"""
config = {'internal_dir': self.internal_dir}
with open(self.config_file, 'w') as f:
json.dump(config, f, indent=4)
def get_timestamp(self):
"""Generate timestamp for filename: YYYYMMDD_HHMMSS"""
return datetime.now().strftime("%Y%m%d_%H%M%S")
def get_unique_filename(self, directory, base_name, extension):
"""
Generate unique filename with auto-numbering
Format: timestamp_base_name.extension
If exists: timestamp_base_name_001.extension, timestamp_base_name_002.extension, etc.
"""
timestamp = self.get_timestamp()
# Clean base_name from invalid characters
base_name = re.sub(r'[<>:"/\\|?*]', '_', base_name)
base_name = base_name[:50] # Limit length
# First attempt: timestamp_base_name.extension
filename = f"{timestamp}_{base_name}.{extension}"
filepath = os.path.join(directory, filename)
if not os.path.exists(filepath):
return filename
# If exists, add numbering: timestamp_base_name_001.extension
counter = 1
while True:
filename = f"{timestamp}_{base_name}_{counter:03d}.{extension}"
filepath = os.path.join(directory, filename)
if not os.path.exists(filepath):
return filename
counter += 1
# Safety limit
if counter > 999:
filename = f"{timestamp}_{base_name}_{int(time.time())}.{extension}"
return filename
def rename_downloaded_files(self, target_dir, owner_username, post_date=None):
"""
Rename downloaded files with timestamp naming convention
Returns list of renamed files
"""
renamed_files = []
if not os.path.exists(target_dir):
return renamed_files
# Get all files in directory (excluding JSON metadata if not needed)
files = [f for f in os.listdir(target_dir) if os.path.isfile(os.path.join(target_dir, f))]
# Filter out txt metadata files (optional)
media_files = [f for f in files if not f.endswith('.txt') and not f.endswith('.json')]
for original_file in media_files:
original_path = os.path.join(target_dir, original_file)
# Get file extension
name_parts = original_file.rsplit('.', 1)
if len(name_parts) < 2:
continue
extension = name_parts[1].lower()
# Determine base name
if post_date:
base_name = f"{owner_username}_{post_date.strftime('%Y%m%d')}"
else:
base_name = owner_username
# Generate unique filename
new_filename = self.get_unique_filename(target_dir, base_name, extension)
new_path = os.path.join(target_dir, new_filename)
try:
os.rename(original_path, new_path)
renamed_files.append({
'original': original_file,
'new': new_filename,
'path': new_path
})
print(f" ✓ Renamed: {original_file} → {new_filename}")
except Exception as e:
print(f" ✗ Error renaming {original_file}: {e}")
return renamed_files
def print_banner(self):
"""Display menu banner"""
os.system('cls' if os.name == 'nt' else 'clear')
print("╔══════════════════════════════╗")
print("║ INSTAGRAM DOWNLOADER ULTRA ║")
print("║ Version 2.1 ║")
print("╠══════════════════════════════╣")
status = "✓ Logged in" if self.current_user else "✗ Guest"
print(f"║ Status: {status:<19} ║")
print("╠══════════════════════════════╣")
print("║ 1. Login ║")
print("║ 2. Load Session ║")
print("║ 3. Download Single Post ║")
print("║ 4. Download Profile (Bulk) ║")
print("║ 5. Download Story ║")
print("║ 6. Download Hashtag ║")
print("║ 7. Move All to Internal ║")
print("║ 8. Settings ║")
print("║ 9. Exit ║")
print("╚══════════════════════════════╝")
print(f"\n💡 Naming: YYYYMMDD_HHMMSS_username_001.jpg")
print()
def login(self):
"""Login to Instagram"""
print("\n[LOGIN INSTAGRAM]")
print("-" * 40)
username = input("Username: ").strip()
if not username:
print("❌ Username cannot be empty!")
return
password = getpass.getpass("Password: ")
try:
print(f"\n🔐 Logging in as {username}...")
self.loader.login(username, password)
self.current_user = username
# Save session
session_path = f"sessions/{username}.session"
self.loader.save_session_to_file(session_path)
print(f"💾 Session saved to: {session_path}")
print(f"✅ Successfully logged in as {username}!")
except instaloader.exceptions.BadCredentialsException:
print("❌ Error: Invalid username or password!")
except instaloader.exceptions.TwoFactorAuthRequiredException:
print("⚠️ 2FA Required!")
code = input("Enter 2FA code: ")
try:
self.loader.two_factor_login(code)
self.current_user = username
print("✅ 2FA Login successful!")
except Exception as e:
print(f"❌ 2FA Error: {e}")
except Exception as e:
print(f"❌ Login Error: {e}")
input("\nPress Enter to continue...")
def load_session(self):
"""Load existing session"""
print("\n[LOAD SESSION]")
print("-" * 40)
sessions = [f for f in os.listdir("sessions") if f.endswith('.session')]
if not sessions:
print("❌ No saved sessions found!")
print("💡 Please login first (Option 1)")
input("\nPress Enter to continue...")
return
print("Available sessions:")
for i, session in enumerate(sessions, 1):
user = session.replace('.session', '')
print(f" {i}. {user}")
choice = input("\nSelect session (number) or type username: ").strip()
try:
if choice.isdigit():
idx = int(choice) - 1
if 0 <= idx < len(sessions):
username = sessions[idx].replace('.session', '')
else:
print("❌ Invalid selection!")
return
else:
username = choice
session_path = f"sessions/{username}.session"
if not os.path.exists(session_path):
print(f"❌ Session for {username} not found!")
return
print(f"\n📂 Loading session for {username}...")
self.loader.load_session_from_file(username, session_path)
self.current_user = username
print("✅ Session loaded successfully!")
# Test session validity
try:
profile = instaloader.Profile.from_username(self.loader.context, username)
print(f"✓ Verified: {profile.full_name} (@{profile.username})")
print(f" Followers: {profile.followers:,} | Following: {profile.followees:,}")
except Exception as e:
print(f"⚠️ Session may be expired: {e}")
except Exception as e:
print(f"❌ Error loading session: {e}")
input("\nPress Enter to continue...")
def download_single_post(self):
"""Download single post by URL or shortcode"""
print("\n[DOWNLOAD SINGLE POST]")
print("-" * 40)
url = input("Enter Post URL or Shortcode: ").strip()
if not url:
print("❌ Input cannot be empty!")
return
# Extract shortcode from URL
shortcode = url
if '/' in url:
parts = url.split('/')
for i, part in enumerate(parts):
if part in ['p', 'reel', 'tv'] and i + 1 < len(parts):
shortcode = parts[i + 1]
break
shortcode = shortcode.replace('/', '').strip()
try:
print(f"\n🔍 Fetching post: {shortcode}...")
post = instaloader.Post.from_shortcode(self.loader.context, shortcode)
print(f"📸 Post by: {post.owner_username}")
print(f"❤️ Likes: {post.likes:,} | 💬 Comments: {post.comments:,}")
print(f"📅 Date: {post.date_utc.strftime('%Y-%m-%d %H:%M:%S')}")
# Create specific folder
target_dir = f"{self.download_dir}/{post.owner_username}"
Path(target_dir).mkdir(parents=True, exist_ok=True)
print(f"\n⬇️ Downloading to: {target_dir}/")
# Temporary download with default naming
temp_dir = os.path.join(target_dir, f"temp_{int(time.time())}")
Path(temp_dir).mkdir(parents=True, exist_ok=True)
# Download post
self.loader.download_post(post, target=temp_dir)
print(f"\n📝 Renaming files with timestamp...")
# Rename files with timestamp and auto-numbering
renamed = self.rename_downloaded_files(temp_dir, post.owner_username, post.date_utc)
# Move files from temp to target
for file_info in renamed:
src = file_info['path']
dst = os.path.join(target_dir, file_info['new'])
shutil.move(src, dst)
# Remove temp directory
shutil.rmtree(temp_dir)
# Move JSON metadata if exists
json_files = [f for f in os.listdir(target_dir) if f.endswith('.json') and f.startswith('temp_')]
for jf in json_files:
os.remove(os.path.join(target_dir, jf))
print(f"\n✅ Download completed!")
print(f"📁 Saved in: {target_dir}/")
print(f"📄 {len(renamed)} file(s) saved with timestamp naming")
except instaloader.exceptions.PostChangedException:
print("❌ Post has been changed or deleted!")
except instaloader.exceptions.BadResponseException:
print("❌ Post not found or private (and not following)!")
except Exception as e:
print(f"❌ Error: {e}")
input("\nPress Enter to continue...")
def download_profile(self):
"""Download profile posts in bulk"""
print("\n[DOWNLOAD PROFILE (BULK)]")
print("-" * 40)
username = input("Enter Instagram Username: ").strip()
if not username:
print("❌ Username cannot be empty!")
return
try:
print(f"\n🔍 Fetching profile: @{username}...")
profile = instaloader.Profile.from_username(self.loader.context, username)
print(f"\n👤 Profile Info:")
print(f" Name: {profile.full_name}")
print(f" Posts: {profile.mediacount:,}")
print(f" Private: {'Yes 🔒' if profile.is_private else 'No 🌐'}")
if profile.is_private and not profile.followed_by_viewer:
print("\n❌ This profile is private and you don't follow them!")
input("\nPress Enter to continue...")
return
# Options
print("\n⚙️ Download Options:")
print(" 1. All posts")
print(" 2. Recent posts only (last 12)")
print(" 3. Posts from specific date range")
print(" 4. Only videos (IGTV/Reels)")
print(" 5. Only photos")
choice = input("\nSelect option (1-5): ").strip()
target_dir = f"{self.download_dir}/{profile.username}"
Path(target_dir).mkdir(parents=True, exist_ok=True)
posts = profile.get_posts()
if choice == "2":
posts = list(posts)[:12]
print(f"\n⬇️ Downloading recent {len(posts)} posts...")
elif choice == "3":
start_date = input("Start date (YYYY-MM-DD): ").strip()
end_date = input("End date (YYYY-MM-DD): ").strip()
try:
start = datetime.strptime(start_date, "%Y-%m-%d")
end = datetime.strptime(end_date, "%Y-%m-%d")
posts = [p for p in posts if start <= p.date_utc <= end]
print(f"\n⬇️ Downloading {len(posts)} posts from {start_date} to {end_date}...")
except:
print("❌ Invalid date format!")
return
elif choice == "4":
posts = [p for p in posts if p.is_video]
print(f"\n⬇️ Downloading {len(posts)} videos...")
elif choice == "5":
posts = [p for p in posts if not p.is_video]
print(f"\n⬇️ Downloading {len(posts)} photos...")
else:
print(f"\n⬇️ Downloading all {profile.mediacount} posts...")
# Download with progress
total_downloaded = 0
for i, post in enumerate(posts, 1):
try:
print(f"\n[{i}] Downloading post from {post.date_utc.strftime('%Y-%m-%d')}...")
# Create temp directory for this post
temp_dir = os.path.join(target_dir, f"temp_{post.shortcode}")
Path(temp_dir).mkdir(parents=True, exist_ok=True)
# Download
self.loader.download_post(post, target=temp_dir)
# Rename files
renamed = self.rename_downloaded_files(temp_dir, profile.username, post.date_utc)
# Move to target
for file_info in renamed:
src = file_info['path']
dst = os.path.join(target_dir, file_info['new'])
shutil.move(src, dst)
# Cleanup temp
shutil.rmtree(temp_dir)
total_downloaded += len(renamed)
# Rate limiting
if i % 10 == 0:
print("⏳ Pausing to avoid rate limit...")
time.sleep(2)
except Exception as e:
print(f" ⚠️ Error: {e}")
continue
print(f"\n✅ Downloaded {total_downloaded} media files!")
print(f"📁 Saved in: {target_dir}/")
except Exception as e:
print(f"❌ Error: {e}")
input("\nPress Enter to continue...")
def download_story(self):
"""Download stories"""
print("\n[DOWNLOAD STORY]")
print("-" * 40)
if not self.current_user:
print("⚠️ Warning: Not logged in. Can only download public stories.")
proceed = input("Continue anyway? (y/n): ").lower()
if proceed != 'y':
return
username = input("Enter Username (or 'self' for your own stories): ").strip()
if not username:
print("❌ Username cannot be empty!")
return
try:
if username.lower() == 'self':
if not self.current_user:
print("❌ Please login first!")
return
profile = instaloader.Profile.from_username(self.loader.context, self.current_user)
else:
profile = instaloader.Profile.from_username(self.loader.context, username)
target_dir = f"{self.download_dir}/{profile.username}_stories"
Path(target_dir).mkdir(parents=True, exist_ok=True)
print(f"\n🔍 Fetching stories from @{profile.username}...")
# Get stories
stories = self.loader.get_stories([profile.userid])
count = 0
for story in stories:
for item in story.get_items():
try:
print(f"\n📥 Downloading story {count+1}...")
# Determine extension
if item.is_video:
ext = "mp4"
else:
ext = "jpg"
# Generate unique filename
base_name = f"{profile.username}_story"
filename = self.get_unique_filename(target_dir, base_name, ext)
filepath = os.path.join(target_dir, filename)
# Download story item
self.loader.download_storyitem(item, target=target_dir)
# Rename the downloaded file
# Find the file that was just downloaded
downloaded_files = [f for f in os.listdir(target_dir)
if f.startswith(str(item.date_utc.strftime('%Y%m%d')))]
for df in downloaded_files:
old_path = os.path.join(target_dir, df)
if os.path.isfile(old_path) and not df.startswith('20'): # Not already renamed
new_path = os.path.join(target_dir, filename)
# If filename taken, get new one
if os.path.exists(new_path):
filename = self.get_unique_filename(target_dir, base_name, ext)
new_path = os.path.join(target_dir, filename)
os.rename(old_path, new_path)
print(f" ✓ Saved as: {filename}")
break
count += 1
except Exception as e:
print(f" ⚠️ Error: {e}")
if count > 0:
print(f"\n✅ Downloaded {count} stories!")
print(f"📁 Saved in: {target_dir}/")
else:
print("\nℹ️ No stories available")
except Exception as e:
print(f"❌ Error: {e}")
input("\nPress Enter to continue...")
def download_hashtag(self):
"""Download posts by hashtag"""
print("\n[DOWNLOAD HASHTAG]")
print("-" * 40)
hashtag = input("Enter Hashtag (without #): ").strip().replace('#', '')
if not hashtag:
print("❌ Hashtag cannot be empty!")
return
try:
print(f"\n🔍 Searching #{hashtag}...")
tag = instaloader.Hashtag.from_name(self.loader.context, hashtag)
print(f"\n🏷️ Hashtag: #{tag.name} | Posts: {tag.mediacount:,}")
limit = input("How many posts to download? (default 50): ").strip()
limit = int(limit) if limit.isdigit() else 50
target_dir = f"{self.download_dir}/#{tag.name}"
Path(target_dir).mkdir(parents=True, exist_ok=True)
print(f"\n⬇️ Downloading up to {limit} posts...")
posts = tag.get_posts()
count = 0
total_media = 0
for post in posts:
if count >= limit:
break
try:
print(f"\n[{count+1}/{limit}] From @{post.owner_username}...")
temp_dir = os.path.join(target_dir, f"temp_{post.shortcode}")
Path(temp_dir).mkdir(parents=True, exist_ok=True)
self.loader.download_post(post, target=temp_dir)
renamed = self.rename_downloaded_files(temp_dir, f"{tag.name}_{post.owner_username}", post.date_utc)
for file_info in renamed:
src = file_info['path']
dst = os.path.join(target_dir, file_info['new'])
shutil.move(src, dst)
shutil.rmtree(temp_dir)
total_media += len(renamed)
count += 1
if count % 10 == 0:
print("⏳ Pausing...")
time.sleep(2)
except Exception as e:
print(f" ⚠️ Error: {e}")
continue
print(f"\n✅ Downloaded {count} posts ({total_media} media files) with #{hashtag}!")
print(f"📁 Saved in: {target_dir}/")
except Exception as e:
print(f"❌ Error: {e}")
input("\nPress Enter to continue...")
def move_to_internal(self):
"""Move all downloads to internal storage"""
print("\n[MOVE TO INTERNAL STORAGE]")
print("-" * 40)
is_android = os.path.exists('/sdcard')
default_path = "/sdcard/InstagramDownloads" if is_android else os.path.expanduser("~/InstagramDownloads")
print(f"Current path: {self.internal_dir}")
new_path = input(f"Destination (Enter for {default_path}): ").strip()
if new_path:
self.internal_dir = new_path
else:
self.internal_dir = default_path
self.save_config()
if not os.path.exists(self.internal_dir):
Path(self.internal_dir).mkdir(parents=True, exist_ok=True)
try:
items = [f for f in os.listdir(self.download_dir)
if os.path.isdir(os.path.join(self.download_dir, f)) and not f.startswith('.')]
if not items:
print("ℹ️ No folders to move!")
return
print(f"\n📦 Found {len(items)} folders to move...")
moved = 0
for item in items:
src = os.path.join(self.download_dir, item)
dst = os.path.join(self.internal_dir, item)
try:
if os.path.exists(dst):
# Merge folders with auto-numbering for conflicts
for root, dirs, files in os.walk(src):
rel_path = os.path.relpath(root, src)
dst_root = os.path.join(dst, rel_path)
Path(dst_root).mkdir(parents=True, exist_ok=True)
for file in files:
src_file = os.path.join(root, file)
# Check if file exists in destination
dst_file = os.path.join(dst_root, file)
if os.path.exists(dst_file):
# Add numbering
name, ext = file.rsplit('.', 1)
counter = 1
while os.path.exists(os.path.join(dst_root, f"{name}_{counter:03d}.{ext}")):
counter += 1
dst_file = os.path.join(dst_root, f"{name}_{counter:03d}.{ext}")
shutil.copy2(src_file, dst_file)
shutil.rmtree(src)
else:
shutil.copytree(src, dst)
shutil.rmtree(src)
moved += 1
print(f" ✓ Moved: {item}")
except Exception as e:
print(f" ✗ Error: {e}")
print(f"\n✅ Moved {moved}/{len(items)} folders!")
print(f"📁 Destination: {self.internal_dir}")
except Exception as e:
print(f"❌ Error: {e}")
input("\nPress Enter to continue...")
def settings(self):
"""Settings menu"""
print("\n[SETTINGS]")
print("-" * 40)
print(f"1. Change internal storage path")
print(f"2. Clear all sessions")
print(f"3. View download statistics")
print(f"4. Back")
choice = input("\nSelect: ").strip()
if choice == "1":
new_path = input("New internal path: ").strip()
if new_path:
self.internal_dir = new_path
self.save_config()
print("✅ Path updated!")
elif choice == "2":
confirm = input("Delete all saved sessions? (yes/no): ").lower()
if confirm == "yes":
sessions = [f for f in os.listdir("sessions") if f.endswith('.session')]
for s in sessions:
os.remove(os.path.join("sessions", s))
print("✅ Sessions cleared!")
elif choice == "3":
self.show_statistics()
input("\nPress Enter to continue...")
def show_statistics(self):
"""Show download statistics"""
print("\n[DOWNLOAD STATISTICS]")
print("-" * 40)
total_folders = 0
total_files = 0
total_size = 0
for root, dirs, files in os.walk(self.download_dir):
total_folders = len(dirs)
for file in files:
filepath = os.path.join(root, file)
total_files += 1
total_size += os.path.getsize(filepath)
print(f"Total folders: {total_folders}")
print(f"Total files: {total_files}")
print(f"Total size: {total_size / (1024*1024):.2f} MB")
print(f"Download directory: {os.path.abspath(self.download_dir)}")
def run(self):
"""Main loop"""
while True:
self.print_banner()
choice = input("Select option (1-9): ").strip()
if choice == '1':
self.login()
elif choice == '2':
self.load_session()
elif choice == '3':
self.download_single_post()
elif choice == '4':
self.download_profile()
elif choice == '5':
self.download_story()
elif choice == '6':
self.download_hashtag()
elif choice == '7':
self.move_to_internal()
elif choice == '8':
self.settings()
elif choice == '9':
print("\n👋 Thank you for using Instagram Downloader Ultra!")
sys.exit(0)
else:
print("\n❌ Invalid option!")
time.sleep(1)
if __name__ == "__main__":
try:
app = InstagramDownloaderUltra()
app.run()
except KeyboardInterrupt:
print("\n\n👋 Goodbye!")
sys.exit(0)
except Exception as e:
print(f"\n💥 Error: {e}")
sys.exit(1)
2️⃣ Paste script Instagram Downloader Ultra v2.1
3️⃣ Simpan → CTRL + X → Y → Enter
4️⃣ Jalankan:
python ig_ultra.py
Nanti akan muncul menu seperti ini:
- Login
- Load Session
- Download Single Post
- Download Profile
- Download Story
- Download Hashtag
- Move All to Internal
- Settings
- Exit
🔐 Fitur Login & Session
Login sekali, session otomatis disimpan di folder:
sessions/username.session
Jadi nggak perlu login berulang-ulang tiap buka script 😌
Kalau akun pakai 2FA?
Script sudah support input kode verifikasi juga 🔥
📸 Download Single Post
Masukkan:
URL post
atau shortcode
Script otomatis:
Ambil data post
Download ke folder sementara
Rename pakai timestamp
Pindahkan ke folder utama
Hapus folder temp
Smart file management banget 👌
👤 Download Profile (Bulk Mode)
Pilihan download:
Semua post
12 post terbaru
Rentang tanggal tertentu
Video saja
Foto saja
Cocok buat:
Backup akun
Arsip konten brand
Simpan referensi konten
Script juga punya delay anti rate limit tiap 10 post ⏳
🔥 Download Story
Bisa download:
Story akun publik
Story akun sendiri (kalau login)
Format file:
YYYYMMDD_HHMMSS_username_story_001.jpg
Auto rename juga, jadi aman 💯
🏷️ Download Hashtag
Masukkan hashtag tanpa tanda #
Contoh:
travel
Script akan:
Ambil post dari hashtag
Batasi jumlah (default 50)
Rename otomatis
Simpan ke folder:
downloads/#travel/
Mantap buat riset konten 🔎
📦 Move ke Penyimpanan Internal
Option 7 akan memindahkan semua folder ke:
/sdcard/InstagramDownloads
Keunggulannya:
Bisa langsung terlihat di Galeri
Bisa dipindah ke laptop
Bisa upload ulang
Bisa dijadikan backup
⚙️ Settings Menu
Di Option 8 kamu bisa:
Ganti path internal storage
Hapus semua session login
Lihat statistik download (total file & ukuran)
Cocok buat yang suka monitoring storage HP 📊
💎 Kenapa Sistem Ini Lebih Aman?
✨ Timestamp unik per detik
✨ Auto-numbering sampai 999
✨ Tidak ada file tertimpa
✨ Sorting otomatis berdasarkan waktu
✨ Folder per username
Ini bikin instagram downloader kamu terasa seperti aplikasi profesional 😎
⚠️ Tips Penting Biar Aman
Jangan spam download ratusan post sekaligus
Gunakan akun sendiri untuk login
Hindari akun private yang tidak kamu follow
Gunakan untuk arsip pribadi & edukasi
🎯 Siapa yang Cocok Pakai Ini?
✔️ Content creator
✔️ Social media manager
✔️ Admin brand
✔️ Pelajar IT yang suka ngoprek
✔️ Kamu yang pengen backup konten sendiri
🚀 Kesimpulan
Dengan kombinasi termux + instagram downloader berbasis Python, kamu bisa bikin sistem download Instagram yang:
Lebih fleksibel dari aplikasi biasa
Tanpa watermark
Tanpa iklan
Tanpa overwrite file
Super rapi & profesional
Dan semua itu cuma dari HP
Tinggalkan komentar atau share artikel ini ke teman kamu yang suka ngulik Termux juga 😎
Jangan lupa save & bookmark ya! 🚀
Posting Komentar