| name | Instagram Access |
| description | Permanent capability skill for authenticated Instagram data extraction using instaloader and a reusable session cookie file |
| recall_keywords | ["instagram","instaloader","download post","download reel","instagram profile","instagram research","social media download","shortcode","instagram asset"] |
Instagram Access — Permanent Capability Skill
What This Skill Enables
- Download posts, reels, and stories from any public Instagram profile
- Download from private profiles the logged-in user follows
- Fetch post metadata (caption, likes, comments, date, type)
- Explore profiles (follower count, bio, post count, recent posts)
- Search by hashtag or location
- Download specific posts by shortcode or URL
- Batch scan captions for content categorization
Authentication
First-Time Setup
You need a dedicated Instagram account for scraping (DO NOT use your main account — Instagram may rate-limit or ban scraper accounts). Create a secondary account, then:
-
Install instaloader:
pip install instaloader --break-system-packages
pip install instaloader
-
Generate a session cookie file (run in a separate terminal, NOT through Claude Code's Bash tool):
instaloader --login <your-scraper-username>
-
Instaloader stores the session at:
- Windows:
%LOCALAPPDATA%\Instaloader\session-<username>.pg (e.g. C:\Users\<you>\AppData\Local\Instaloader\session-<username>.pg)
- macOS/Linux:
~/.config/instaloader/session-<username>.pg
-
Record the username and session path in your project's configuration (NOT in this skill — keep credentials out of version control).
If Session Expires
The session eventually expires. When instaloader throws LoginRequiredException or ConnectionException with "redirected to login":
- Tell the user: "Instagram session expired. Please re-authenticate."
- User runs in a separate terminal (NOT through Claude Code's Bash):
instaloader --login <username>
- User enters password interactively (Bash tool cannot handle password prompts)
- Session file is refreshed automatically
- Resume operations
NEVER attempt interactive login through the Bash tool. It cannot handle password prompts.
How to Use — Code Patterns
Load Session (always start with this)
import instaloader
L = instaloader.Instaloader(
download_videos=True,
download_video_thumbnails=False,
compress_json=False,
save_metadata=False,
download_geotags=False,
download_comments=False,
post_metadata_txt_pattern=""
)
L.load_session_from_file("<username>")
Get Profile Info
profile = instaloader.Profile.from_username(L.context, "<target-username>")
print(f"Followers: {profile.followers}, Posts: {profile.mediacount}")
print(f"Bio: {profile.biography}")
Get Post by Shortcode
post = instaloader.Post.from_shortcode(L.context, "<shortcode>")
print(f"Date: {post.date_utc}, Likes: {post.likes}, Type: {post.typename}")
print(f"Caption: {post.caption}")
Download a Single Post
L.download_post(post, target="output_directory")
Iterate Profile Posts
for post in profile.get_posts():
print(post.shortcode, post.caption[:50])
time.sleep(2)
Search by Hashtag
hashtag = instaloader.Hashtag.from_name(L.context, "<hashtag>")
for post in hashtag.get_posts():
print(post.shortcode)
time.sleep(2)
Extract Shortcode from URL
import re
url = "https://www.instagram.com/p/<shortcode>/"
shortcode = re.search(r'/(p|reel)/([A-Za-z0-9_-]+)', url).group(2)
Windows-Specific Handling
UTF-8 Encoding (required for non-Latin captions)
Always add at the top of any script:
import sys, io, os
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
os.environ["PYTHONIOENCODING"] = "utf-8"
Filename Safety
Instaloader creates files with timestamps containing colons — invalid on Windows. Always sanitize filenames:
import re
safe_name = re.sub(r'[<>:"/\\|?*]', '_', original_name)
File Writing with Non-Latin Content
with open(filepath, "w", encoding="utf-8") as f:
f.write(caption_with_non_latin)
Safety Rules
- NEVER store passwords in any file
- NEVER open Chrome or any browser
- NEVER create directory junctions
- Add 2-3 second delays between API calls (reels: 3-5 seconds)
- If rate limited (429 or "Please wait"): wait 60 seconds, retry once, then skip
- If session expired: tell the user to re-authenticate in a separate terminal
- NEVER download from accounts the user does not follow (respect privacy)
- NEVER use Instagram data for purposes other than what the user requests
- All filenames must be plain ASCII — replace special characters with hyphens
- ZERO non-Latin characters in terminal commands or filenames
Common Tasks
"Download photos from @someprofile"
profile = instaloader.Profile.from_username(L.context, "someprofile")
for post in profile.get_posts():
L.download_post(post, target="downloads")
time.sleep(3)
"Get captions from recent 20 posts of @profile"
profile = instaloader.Profile.from_username(L.context, "profile")
for i, post in enumerate(profile.get_posts()):
if i >= 20: break
print(f"{post.shortcode}: {post.caption[:100]}")
time.sleep(1.5)
"Download this specific post: [URL]"
shortcode = re.search(r'/(p|reel)/([A-Za-z0-9_-]+)', url).group(2)
post = instaloader.Post.from_shortcode(L.context, shortcode)
L.download_post(post, target="downloads")
"Research competitor @profile"
profile = instaloader.Profile.from_username(L.context, "competitor")
info = {
"username": profile.username,
"full_name": profile.full_name,
"bio": profile.biography,
"followers": profile.followers,
"following": profile.followees,
"posts": profile.mediacount,
"is_verified": profile.is_verified,
"is_business": profile.is_business_account,
"business_category": profile.business_category_name,
}
likes, comments = [], []
for i, post in enumerate(profile.get_posts()):
if i >= 20: break
likes.append(post.likes)
comments.append(post.comments)
time.sleep(1.5)
info["avg_likes"] = sum(likes) / len(likes) if likes else 0
info["avg_comments"] = sum(comments) / len(comments) if comments else 0
Recall Keywords
instagram, instaloader, download post, download reel, instagram profile,
instagram research, social media download, shortcode, instagram asset