Repository navigation
Differences from Instaloader
Jimmy Nordström edited this page Nov 13, 2026
·
9 revisions
InstaloaderSharp follows Instaloader closely, but it puts working correctly before reproducing Instaloader's behavior. Where Instaloader fails because Instagram changed, or because of a bug, InstaloaderSharp is fixed and differs deliberately. This page lists every such difference.
| Feature | Instaloader | InstaloaderSharp |
|---|---|---|
:feed |
Pages through the app's timeline (api/v1/feed/timeline/), which returned about two posts per request in a test, between suggestions |
Loads the feed the way Instagram's website does: the first page from the home page, further pages with the query the home page declares, which returns the same posts with fewer requests. Instagram's suggested posts from accounts you do not follow are skipped |
:stories |
Uses a query for the list of accounts with stories that Instagram no longer answers | Gets the list from the app's story tray (api/v1/feed/reels_tray/) |
Followers and followees (@profile, Profile.GetFollowers(), GetFollowees()) |
Its query returns no profiles | Uses the friendships interface of Instagram's web app |
Geotags (--geotags) |
Fails with KeyError: 'id': Instagram now names the location ID pk and no longer provides slug and has_public_page; the fallback lookup returns no data either |
Works, also without logging in. In saved metadata, a post's location has no slug
|
--igtv |
Fails with KeyError: 'edges'
|
Reports that Instagram has retired IGTV; former IGTV videos are downloaded as posts and reels. Lists that Instagram returns without items are treated as empty instead of failing |
Profile.GetFollowedHashtags() |
Fails with a TypeError
|
Returns an empty list, since Instagram removed following hashtags in December 2024 |
| Restricted profiles (for example age-restricted ones) | Reports Profile ... does not exist.: it reads profiles from their page as a logged-out visitor sees it, and Instagram does not show restricted profiles to logged-out visitors |
Found when logged in: the profile's ID is read from the profile page as the session sees it, and the profile is loaded by its ID |
Tagged posts (--tagged) |
Downloads only the first few tagged posts: its query returns a first page of a few posts, followed by empty pages | Downloads all tagged posts, with the query of the website's tagged tab (PolarisProfileTaggedTabContentQuery_connection). That query returns the posts without their dates and videos, so each tagged post is loaded with an extra request |
Searching Instagram (TopSearchResults in library use) |
Uses the website's top search, which Instagram has retired (404) | Uses the search of Instagram's app (api/v1/fbsearch/topsearch_flat/, and api/v1/fbsearch/places/ for places). Requires login; throws LoginRequiredException otherwise |
| Suggestions of similar profile names | When a profile cannot be loaded, tries the website's top search, which Instagram has retired (404), several times | Not made; the error is Profile ... does not exist.
|
Stories and highlights (--stories, --highlights, :stories) |
For some accounts, Instagram answers its queries with a redirect to its home page, and no stories or highlights are downloaded | Works; see below |
Highlights whose items Instagram refuses to list (400 invalid request) |
Stops downloading the profile's highlights | Takes the items from the app's reels_media answer; if a highlight still fails, the other highlights are downloaded |
| Single posts, reels and profile details, logged in | For some accounts, Instagram answers these queries with a redirect to its home page (HTTP redirect from https://www.instagram.com/graphql/query to https://www.instagram.com/), and they cannot be loaded |
Works; see below |
-
Logged-in queries are sent like the website's. Since October 2026, Instagram redirects logged-in GraphQL queries to its home page, for some accounts, unless they carry the session's request token (
fb_dtsg, from Instagram's home page), the query's name and the browser'sSec-Fetch-*headers. InstaloaderSharp sends them for queries of reels, tagged posts, post details, profile details and further pages of:feed. Instaloader sends profile posts the website's way too, through the website'sapi/graphqlendpoint, but its other logged-in queries without these fields. Reels are loaded with the query of the website's reels tab (PolarisProfileReelsTabContentQuery_connection), since Instagram answers Instaloader's older reels query without reels when it is sent this way. -
The login check asks the app interface. Whether a session is logged in, and as whom, is checked with Instagram's app interface (
api/v1/accounts/current_user/). Instaloader uses a GraphQL query that Instagram redirects to its home page for some accounts, so that a valid session is reported asNot logged in. Are you logged in successfully in firefox?, after threeHTTP redirect from https://www.instagram.com/graphql/query to https://www.instagram.com/messages. That query is still used as a fallback, and with--no-iphone. -
Stories and highlights come from the app interface. The stories and the highlights' items are loaded from Instagram's app interface (
api/v1/feed/reels_media/), the list of highlights fromapi/v1/highlights/<ID>/highlights_tray/. Instaloader uses GraphQL queries that Instagram redirects to its home page for some accounts, so that--storiesand--highlightsend withDownload stories: JSON Query to graphql/query: Expecting value: line 1 column 1 (char 0). Instaloader's queries are still used when the app does not answer, and with--no-iphone. The saved metadata of story items then has fewer GraphQL fields; the app's complete item is iniphone_struct, as before. -
No extra request for the video versions. Logged in, a video whose details already contain its video versions (as those of reels, tagged posts and single posts do) is downloaded without asking Instagram's app for its media info (
api/v1/media/<ID>/info/). Instaloader asks for it for every video, for the best version; the versions in it were the same sizes and files in all 956 videos compared, so the same file is downloaded. Each reel takes one request instead of two: the first--reelsdownload of a profile with 1,200 reels took about 2,500 requests, enough for Instagram to flag the account (a captcha, thenfeedback_required). The saved metadata of these videos has noiphone_struct. - Lower limits when logged in. Logged in, the program allows half as many requests as Instaloader within the same time; see Rate limits and connections. Logged out, Instaloader's limits apply.
- A verification page stops the download. When Instagram answers a logged-in query with a web page instead of data, usually a verification (captcha), the download stops (exit code 4) instead of retrying; see Rate limits and connections. Instaloader retries, and goes on with the next targets, which get the same page.
-
A redirect to the verification page stops at once. When Instagram redirects a query to its verification page (
/challenge/), the program stops withInstagram asks to verify the account: it redirected ... to its verification page: while the login is checked with exit code 3, during a download with exit code 4. Instaloader retries the login check three times and then reportsNot logged in. Are you logged in successfully in firefox?, although the session is valid. -
No endless redirects. For a suspended or restricted account, Instagram redirects every request to its home page, and the home page to itself. Instaloader then follows the redirects forever, printing
HTTP redirect from ... to https://www.instagram.com/again and again. InstaloaderSharp follows at most 10 redirects and never the same one twice; logged in, it then stops the download (exit code 4) with the messageInstagram keeps redirecting ... The account may be suspended, restricted or logged out; check it in a web browser.
-
Formatted values are cleaned. Values with a format specification in
--dirname-patternand--filename-pattern, such as{date_utc:%c}or{date_utc:%H:%M}, get the same replacements of characters that are invalid in Windows file names as other values (:becomes:). Instaloader leaves them unchanged and fails withOSError: [Errno 22] Invalid argument. Path separators from formats are kept, so{date_utc:%Y/%m}still creates subfolders.
-
--load-cookiesis built in. Instaloader needs the optionalbrowser_cookie3package. InstaloaderSharp supports Firefox, LibreWolf and the Chromium-based browsers on Windows itself. Cookies with Chrome's app-bound encryption (v20) cannot be decrypted, as withbrowser_cookie3, and Chrome may need to be closed so that its cookie database can be read. Safari only exists on macOS.
- Syntax errors in filters are reported as an error message, with exit code 2, instead of a Python traceback.
- Several profiles are downloaded in the order they were given, instead of in the order of Python's set.
InstaloaderSharp is a Windows program for .NET Framework. It has no Python API; its library is a .NET API with the same structure as Instaloader's Python API.
Getting going
Downloading
- Choosing what to download
- Keeping an archive up to date
- Filtering posts and stories
- File and folder names
- Interrupting and resuming
- Rate limits and connections
Reference
- Command-line options
- Properties reference
- File formats
- Interoperability with Instaloader
- Differences from Instaloader
- Library use
- Troubleshooting and FAQ
- Glossary
Project