Skip to content

Timelines ​

Fetch home timelines and other feed-like content.

Response format ​

All timeline methods return a parsed object:

js
{
  tweets: [ /* parsed tweet objects, pinned tweet first */ ],
  users: [ /* parsed user objects (when applicable) */ ],
  pinned: { /* the profile's pinned tweet, or null */ },
  modules: [ /* grouped entries, see below */ ],
  cursors: [ /* extra cursors like "show more replies" */ ],
  notifications: [ /* parsed notifications (notification timelines only) */ ],
  unreadAfterSortIndex: "1781884986996", // notifications newer than this are unread
  nextCursor: "DAABCgAB...",      // pass to opts.cursor for the next page
  previousCursor: "DAABCgAA...",  // pass to opts.cursor to go back
  raw: { /* original Twitter response */ },
}

tweets is still a flat list. modules keeps the grouping Twitter sends: on HomeTimeline a home-conversation-* module is a reply chain, and on TweetDetail each conversationthread-* module is one reply thread. Each module is { id, type, tweets: [tweetId], users: [userId], cursor }, where cursor is the "show more replies" cursor for that thread, if any. Pass it to opts.cursor of the same call to load the rest of the thread.

Promoted tweets have promoted: true and an ad object with the advertiser, the call to action and the destination, the pinned tweet has pinned: true, and tweets shown with a context line ("Twitter liked", "Pinned") carry the raw social_context.

timelines.home(opts?) ​

Get your home timeline (algorithmic). Uses the GraphQL HomeTimeline query.

OptionTypeDescription
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.topicstringA topic id from timelines.topics(), turns this into that custom timeline
opts.snoozestring[]Topic ids to leave out of the timeline (Twitter's "Snooze topics")
opts.variablesobjectAdditional GraphQL variables
js
const { tweets, nextCursor } = await client.timelines.home();
console.log(tweets[0].text);

// Paginate
const page2 = await client.timelines.home({ cursor: nextCursor });

// Fetch more
const big = await client.timelines.home({ count: 50 });

timelines.topics() ​

List the topics Twitter offers as custom timelines, the Grok-curated feeds Twitter shows as extra Home tabs, plus the communities you can pin. Uses the GraphQL PinnableTimelines query.

js
const { topics, communities } = await client.timelines.topics();
// topics: [{ id: "1925953013547450368", name: "Artificial Intelligence", label: "AI",
//            description: "Artificial Intelligence, AI, Machine Learning, ...",
//            icon: "topic_ai", iconUrl: null }, ...]

timelines.topic(id, opts?) ​

Get a custom timeline for one topic. It's timelines.home({ ...opts, topic: id }), so it takes the same options, including snooze.

js
const ai = await client.timelines.topic("1925953013547450368");
const next = await client.timelines.topic("1925953013547450368", { cursor: ai.nextCursor });

Snoozing topics ​

Twitter keeps snoozes on the client: the web app remembers which topics you snoozed and for how long (24 hours), and sends them as negated topicIds on every HomeTimeline request. emusks does the same through opts.snooze. It takes plain topic ids and adds the minus sign itself. Remembering the 24 hours is up to you.

js
const calm = await client.timelines.home({ snooze: ["1925952771733262336", "1925949693290295298"] });

timelines.homeLatest(opts?) ​

Get your home timeline sorted by latest (chronological). Uses the GraphQL HomeLatestTimeline query.

OptionTypeDescription
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const { tweets } = await client.timelines.homeLatest();

timelines.connect(opts?) ​

Get the "Connect" tab timeline (who to follow suggestions, etc.). Uses the GraphQL ConnectTabTimeline query.

OptionTypeDescription
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const { users } = await client.timelines.connect();

timelines.moderated(opts?) ​

Get the moderated timeline (tweets hidden from your profile). Uses the GraphQL ModeratedTimeline query.

OptionTypeDescription
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const { tweets } = await client.timelines.moderated();

timelines.creatorSubscriptions(opts?) ​

Get the creator subscriptions timeline. Uses the GraphQL CreatorSubscriptionsTimeline query.

OptionTypeDescription
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const { tweets } = await client.timelines.creatorSubscriptions();

timelines.videoMixer(opts?) ​

Get the video feed of the x.com media tab. Uses the GraphQL MediaTabVideoMixer query. It takes no count or cursor, so each call returns a fresh batch.

js
const { tweets } = await client.timelines.videoMixer();

timelines.tvHome(opts?) ​

Get the video feed of the Twitter TV home screen. Uses the GraphQL TVHomeMixer query. It takes no count or cursor, and a test call returned 82 video posts.

js
const { tweets } = await client.timelines.tvHome();

Pagination ​

All timeline methods return nextCursor and previousCursor automatically. Pass them as opts.cursor:

js
// First page
const page1 = await client.timelines.home({ count: 20 });
console.log(page1.tweets);

// Next page
const page2 = await client.timelines.home({ cursor: page1.nextCursor });

// Collect multiple pages
const allTweets = [];
let cursor;
for (let i = 0; i < 5; i++) {
  const page = await client.timelines.home({ count: 20, cursor });
  allTweets.push(...page.tweets);
  cursor = page.nextCursor;
  if (!cursor) break;
}

timelines.updatePinned(pinnedTimelineItems) ​

Set the pinned timelines shown as tabs on your home screen (lists, communities, etc.). Uses the GraphQL UpdatePinnedTimelines mutation. Pass the full ordered array of pinned timeline items.

js
await client.timelines.updatePinned([
  { /* pinned timeline item */ },
]);

timelines.feedback(encodedFeedbackRequest, opts?) ​

Untested

This mutation was built from the x.com web bundle and has not been run against a live account.

Send timeline feedback such as "Not interested in this post". Uses the GraphQL timelinesFeedback mutation. Timeline entries carry their feedback actions in the raw response, each with an encodedFeedbackRequest string. Pass { undo: true } to take the feedback back.

js
await client.timelines.feedback(encodedFeedbackRequest);
await client.timelines.feedback(encodedFeedbackRequest, { undo: true });

not affiliated with X Corp.