Skip to content

Reels ​

What the person sees. A reel shown full-screen (ReelsViewerScreen): the screen behind the bottom bar's Reels tab, and the one a timeline reel or a profile's clip opens.

What you do. You swipe from reel to reel, ask for the next page of the stream, and leave the viewer with back() when it was pushed over another screen. It is one screen for every entry, and where it was opened from decides its first page: the tab sends the stream's first page, a profile's clip opens on that profile's list with no request, and a timeline reel opens on the reel it names with no request.

The Reels viewerThe Reels viewer: current is the reel in front.

Every example starts from session.json, the session Your first program saved, and names the screen it expects (screen: FeedTimelineScreen). The examples show the success path: errors are answered as in Errors, and challenges by your otherwise constant (Challenges: answer them once with otherwise).

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

// A checkpoint read back from your storage (see "Keep a session").
const saved = JSON.parse(await readFile('session.json', 'utf8'));

The matrix ​

#The person...Starts onActionsResult
1Opens the Reels tab and watchesthe feedopenReelsTab(), currentThe viewer with the stream's first page; the reel in front
2Swipes through the reelsthe Reels tabswipeToNext(); nextPage() for the next stream pageThe reel that comes in front; past the loaded reels the next page is loaded
3Plays a reel of the timelinethe feedthe reel item's open({}), swipeToNext(), back()The viewer on that reel; closing it writes the seen state
4Plays a clip of a profile's Reels taba profile's Reels tabthe clip's open(), swipeToNext()The viewer on the profile's list at that clip

Each reel is an item: viewing is timed from the moment the reel is in front, as in the app, and a like reports it. The reel's like and openComments belong to the likes, reposts and comments area and are documented with it.

The scenarios ​

1. Open the Reels tab ​

ts
// Open the Reels tab and watch the reel in front.
const inFront = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: feed =>
    Effect.gen(function* () {
      // The tab sends the stream's first page. The edge lands on the viewer, the tab's root.
      const tab = yield* feed.openReelsTab();
      return tab.current?.key;
    }),
});
console.log(inFront);

Your own reel in the viewerYour own reel shows "View insights" and "Boost"; the Simulator offers no action for them.

2. Swipe through the reels ​

swipeToNext() moves to the reel that comes in front and, past the loaded reels, loads the next stream page itself; nextPage() is the raw page request without a swipe, and answers undefined at the stream's end.

ts
// Swipe through the reels: every swipe moves to the next reel and, past the loaded ones, loads the next page.
const watched = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: feed =>
    Effect.gen(function* () {
      const tab = yield* feed.openReelsTab();
      const keys: string[] = [];
      // Viewing is the reel's visit: the swipe leaves this reel and enters the next.
      let reel = tab.current;
      for (let seen = 0; reel !== undefined && seen < 5; seen += 1) {
        keys.push(reel.key);
        reel = yield* tab.swipeToNext();
      }
      return keys;
    }),
});
console.log(watched);

3. Play a reel of the timeline ​

The viewer was pushed over the timeline, so it has back(). Leaving it sends the seen state with the reels visited. The Reels tab's root has no back().

ts
// Play a reel the timeline shows, swipe once and close the viewer: leaving it writes the seen state.
const fromTimeline = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: feed =>
    Effect.gen(function* () {
      const item = feed.items.find(candidate => FeedTimelineReelItem.is(candidate));
      if (item === undefined || !FeedTimelineReelItem.is(item)) return undefined;
      // The viewer opens on the tapped reel and sends no page request; `{}` means no options.
      const viewer = yield* item.open({});
      yield* viewer.swipeToNext();
      // The viewer was pushed over the timeline, so it has `back()`; the Reels tab's root has none.
      yield* viewer.back();
      return 'closed';
    }),
});
console.log(fromTimeline);

4. Play a clip of a profile ​

The viewer opened from a profile's Reels tabThe viewer opened from a profile's Reels tab: it starts on that profile's list.

ts
// Play a clip from a profile's Reels tab: the viewer opens on that profile's list.
const fromProfile = await AndroidIgpapi.launch({
  checkpoint: saved,
  screen: FeedTimelineScreen,
  main: feed =>
    Effect.gen(function* () {
      const tab = yield* feed.openSearchTab();
      let typed = yield* tab.openSearchInput();
      typed = yield* typed.change('instagram');
      const results = yield* typed.search('instagram');
      const users = yield* results.openUsers();
      const first = users.results[0];
      if (first === undefined) return undefined;
      const profile = yield* first.openProfile();
      const reels = yield* profile.openReelsTab();
      const clip = reels.clips[0];
      if (clip === undefined) return undefined;
      const viewer = yield* clip.open();
      // The list is the viewer's first page, so swiping forward needs no request until the list ends.
      const second = yield* viewer.swipeToNext();
      return second?.key;
    }),
});
console.log(fromProfile);

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