Skip to content

Lists: followers, following and other feeds ​

A list of Instagram that has no screen, such as the followers of an account, is a feed. A feed is an effect that opens a cursor; its next effect loads the following page and reports whether there is more. The lists the screens show (the home feed, a profile's posts, the Reels viewer) are walked with nextPage() and swipeToNext() instead (Work with screens).

You call a feed inside the main of an entry, like any effect that has no screen (Effects inside main).

Page through a list ​

ts
import { AndroidIgpapi, FeedTimelineScreen, followersFeed } from '@igpapi/android';
import { Effect } from 'effect';
import { readFile } from 'node:fs/promises';

const saved = JSON.parse(await readFile('session.json', 'utf8'));

const total = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: _feed =>
    Effect.gen(function* () {
      // A feed is an effect that opens a cursor; its `next` effect loads one page.
      const followers = yield* followersFeed({ id: '123456' });
      const page = yield* followers.next;
      let count = page.items.length;

      let more = page.hasMore;
      while (more) {
        const nextPage = yield* followers.next;
        count += nextPage.items.length;
        more = nextPage.hasMore;
      }
      return count;
    }),
});
console.log(total);

followersFeed({ id }) takes the account's id; followingFeed takes the same input. Both are exported by @igpapi/android, as are the other feeds (saved posts, liked posts, blocked users and more): the API reference lists them together under the lists category, with the input of each.

Save a cursor ​

A feed's cursor says where the next page starts. feed.checkpoint is that cursor, an object you can store and give back to the feed later, so a long list is read over several runs.

ts
import { AndroidIgpapi, FeedTimelineScreen, followersFeed } from '@igpapi/android';
import { Effect } from 'effect';
import { readFile, writeFile } from 'node:fs/promises';

const saved = JSON.parse(await readFile('session.json', 'utf8'));

// The first two pages, and the cursor that says where to go on.
const cursor = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: _feed =>
    Effect.gen(function* () {
      const feed = yield* followersFeed({ id: '123456' });
      yield* feed.next;
      yield* feed.next;
      return yield* feed.checkpoint;
    }),
});
await writeFile('feed-cursor.json', JSON.stringify(cursor));

// Later, in another program: a saved cursor is an object, so parse what the storage returns.
const resumeFrom = JSON.parse(await readFile('feed-cursor.json', 'utf8'));
const items = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: _feed =>
    Effect.gen(function* () {
      const resumed = yield* followersFeed(resumeFrom);
      const page = yield* resumed.next;
      return page.items.length;
    }),
});
console.log(items);

The pages of this site are the README files of the repository. The API reference is generated from the source.