Repository navigation
Library use
InstaloaderSharp.exe is also a .NET library. Your own C# (or other .NET) program can reference it and use the same classes the command line uses, to download items, read their metadata or build your own tools. The API follows Instaloader's Python API, with .NET naming.
- Setting up a project
- Naming
- The main classes
- Downloading a profile
- Options
- Logging in
- Reading metadata
- Single posts, hashtags, stories and highlights
- Saving and loading metadata files
- Resumable downloads
- Filters
- Errors and Ctrl+C
- Things to keep in mind
- Create a project for .NET Framework 4.8.1 (for example a console application in Visual Studio).
- Add a reference to
InstaloaderSharp.exe(Project → Add Reference → Browse), and toSystem.Numerics. - Copy
InstaloaderSharp.exenext to your program, or let Visual Studio do it (Copy Local).
All classes are in the namespace InstaloaderSharp; Interrupt is in InstaloaderSharp.Util. The library has the same requirements as the program: Windows 10 1607 or later and .NET Framework 4.8.1.
Python names map to .NET names in PascalCase:
| Python (Instaloader) | C# (InstaloaderSharp) |
|---|---|
instaloader.Instaloader() |
new Instaloader() |
L.download_post(post, target) |
L.DownloadPost(post, target) |
Profile.from_username(L.context, name) |
Profile.FromUsername(L.Context, name) |
post.date_utc, post.caption_hashtags
|
post.DateUtc, post.CaptionHashtags
|
| keyword arguments | named arguments: new Instaloader(downloadVideos: false)
|
KeyboardInterrupt |
KeyboardInterruptException |
with L.context.error_catcher(...): |
L.Context.ErrorCatcher(..., () => { ... }) |
with resumable_iteration(...): |
NodeIteration.ResumableIteration(..., body: ...) |
Numbers that Instagram may leave out are nullable (long? Likes, long? Followers). Raw JSON is represented by the JObject and JToken classes in InstaloaderSharp.Json.
| Class | Purpose |
|---|---|
Instaloader |
Downloading: posts, stories, highlights, profiles, feed, saved posts, hashtags, locations; logging in; sessions. Its constructor takes the command-line options |
InstaloaderContext |
The connection to Instagram (L.Context): requests, rate limiting, login state, error log |
Profile |
A profile: properties, and its posts, tagged posts, reels, followers and followees |
Post |
A post: properties, comments, likes, sidecar items |
StoryItem, Story, Highlight
|
Story items, a profile's current story, highlights |
Hashtag |
A hashtag and its posts |
PostLocation, PostComment, PostSidecarNode
|
Parts of a post |
NodeIterator<T> |
A list of items fetched from Instagram page by page, which can be frozen and resumed |
Structures |
Saving and loading metadata files (SaveStructureToFile, LoadStructureFromFile) |
LatestStamps |
The --latest-stamps database |
The properties of these classes are listed in Properties reference.
using System.Linq;
using InstaloaderSharp;
class Example
{
static void Main()
{
using (var L = new Instaloader())
{
Profile profile = Profile.FromUsername(L.Context, "instagram");
foreach (Post post in profile.GetPosts().Take(10))
L.DownloadPost(post, profile.Username);
}
}
}DownloadPost saves the post with the current options into the folder given by --dirname-pattern (default {target}, here instagram). It returns true if something was downloaded and false if all files existed.
The complete download of the command line, including profile picture, metadata and the options for stories and highlights, is L.DownloadProfiles(...).
The constructor of Instaloader takes the options of the command line as named arguments:
var L = new Instaloader(downloadVideos: false,
compressJson: false,
dirnamePattern: @"D:\Instagram\{profile}",
filenamePattern: "{date_utc:%Y-%m-%d}_{shortcode}");| Argument | Option |
|---|---|
sleep |
Pauses between requests (true; never turn off for real downloads) |
quiet |
--quiet |
userAgent |
--user-agent |
dirnamePattern, filenamePattern, titlePattern
|
--dirname-pattern, --filename-pattern, --title-pattern
|
downloadPictures, downloadVideos, downloadVideoThumbnails
|
--no-pictures, --no-videos, --no-video-thumbnails
|
downloadGeotags, downloadComments
|
--geotags, --comments
|
saveMetadata, compressJson
|
--no-metadata-json, --no-compress-json
|
postMetadataTxtPattern, storyitemMetadataTxtPattern
|
--post-metadata-txt, --storyitem-metadata-txt
|
maxConnectionAttempts, requestTimeout
|
--max-connection-attempts, --request-timeout
|
resumePrefix |
--resume-prefix; null is --no-resume
|
slide |
--slide |
fatalStatusCodes |
--abort-on |
iphoneSupport |
--no-iphone |
sanitizePaths |
--sanitize-paths |
rateController |
A function creating a custom RateController, to change the request limits |
using (var L = new Instaloader())
{
// Use a saved session (as with --login), ...
L.LoadSessionFromFile("YOUR-USERNAME");
// ... or log in with a password.
try
{
L.Login("YOUR-USERNAME", password);
}
catch (TwoFactorAuthRequiredException)
{
L.TwoFactorLogin(code);
}
L.SaveSessionToFile();
Console.WriteLine(L.TestLogin()); // the logged-in username, or null
}L.InteractiveLogin(username) asks for the password (and two-factor code) on the console, like the command line. L.Context.IsLoggedIn and L.Context.Username tell the login state.
Properties are fetched from Instagram when they are first used, so reading metadata needs no downloads:
Profile profile = Profile.FromUsername(L.Context, "instagram");
Console.WriteLine("{0} ({1}): {2} posts, {3} followers",
profile.Username, profile.FullName, profile.Mediacount, profile.Followers);
foreach (Post post in profile.GetPosts().Take(5))
Console.WriteLine("{0:yyyy-MM-dd} {1} likes {2}",
post.DateUtc, post.Likes, string.Join(" ", post.CaptionHashtags));Other lists of a profile: GetTaggedPosts(), GetReels(), GetSavedPosts() (your own profile, logged in), GetFollowers() and GetFollowees() (logged in). Of a post: GetComments(), GetLikes(), GetSidecarNodes().
Post post = Post.FromShortcode(L.Context, "DdwalmrkTSK");
L.DownloadPost(post, "single");
foreach (Post p in Hashtag.FromName(L.Context, "sunset").GetPostsResumable().Take(20))
L.DownloadPost(p, "#sunset");
// Logged in:
foreach (Story story in L.GetStories(new[] { profile.Userid }))
foreach (StoryItem item in story.GetItems())
L.DownloadStoryitem(item, profile.Username);
L.DownloadHighlights(profile);Further downloads: L.DownloadFeedPosts(maxCount: 50), L.DownloadSavedPosts(), L.DownloadLocation("123456789"), L.DownloadTagged(profile), L.DownloadReels(profile), L.DownloadProfilepic(profile).
Structures.SaveStructureToFile(post, "post.json.xz");
var loaded = (Post)Structures.LoadStructureFromFile(L.Context, "post.json.xz");The files are the same as those of the command line and of Instaloader; see File formats. LoadStructureFromFile returns a Post, StoryItem, Profile, Hashtag or FrozenNodeIterator.
A NodeIterator<T> can save its position and continue later. NodeIteration.ResumableIteration does this the way the command line does: it resumes from a file if one exists, saves the position if the body throws, and deletes the file when the body completes.
NodeIterator<Post> posts = profile.GetPosts();
NodeIteration.ResumableIteration(
context: L.Context,
iterator: posts,
load: (ctx, path) => Structures.LoadStructureFromFile(ctx, path),
save: (frozen, path) => Structures.SaveStructureToFile(frozen, path),
formatPath: magic => "resume_" + magic + ".json.xz",
checkBbd: true,
enabled: true,
body: (isResuming, startIndex) =>
{
foreach (Post post in posts)
L.DownloadPost(post, profile.Username);
});posts.Freeze() and posts.Thaw(frozen) save and restore the position directly.
The command line's filter expressions can be used in your own code:
Func<Post, bool> filter = Program.FilterstrToFilterfunc<Post>("likes > 1000 and not is_video");The function throws InvalidArgumentException for an invalid expression. See Filtering posts and stories.
- Errors are reported as exceptions derived from
InstaloaderException:ProfileNotExistsException,LoginRequiredException,PrivateProfileNotFollowedException,ConnectionException(withQueryReturnedNotFoundExceptionandTooManyRequestsException),LoginException(withBadCredentialsExceptionandTwoFactorAuthRequiredException),InvalidArgumentExceptionand others.AbortDownloadException(not anInstaloaderException) means that Instagram demanded a verification and the download must stop. -
L.Context.ErrorCatcher("description", () => { ... })runs an action, catchesInstaloaderExceptions, prints them and keeps them for the summary at the end, like the command line does for each target.L.HasStoredErrorstells whether there were any. -
Interrupt.Install()makes Ctrl+C throw aKeyboardInterruptExceptionat the next request or pause instead of ending the process, so that resume information can be saved. Without it, Ctrl+C ends your program immediately.
Interrupt.Install();
try
{
foreach (Post post in profile.GetPosts())
L.Context.ErrorCatcher("Download " + post.Shortcode, () => L.DownloadPost(post, profile.Username));
}
catch (KeyboardInterruptException)
{
Console.WriteLine("Interrupted.");
}- Keep
sleep: true(the default) and the default rate controller for real downloads; without the pauses and limits Instagram quickly blocks the account. -
Instaloaderand its context are not thread-safe. Use one instance per thread, and do not run several instances with the same account at the same time. - Dispose the
Instaloader(using) to close its connections. - Lists are fetched lazily: iterating a
NodeIteratormakes requests as it goes, so useTake(...)to limit them. - The library writes progress messages to the console like the command line, unless
quiet: trueis given.
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