dilame / instagram-private-api

NodeJS Instagram private API SDK. Written in TypeScript.
MIT License
5.93k stars 1.14k forks source link

Retrieving messages that contain reels: "Use the latest version of the Instagram app to see this reel" #1713

Closed continue47 closed 1 year ago

continue47 commented 1 year ago

Form

Put an [x] if you meet the condition, else leave [ ].

Question

If a message contains a reel shared with the user, the object returned contains a placeholder property which says to update to the latest version of the Instagram app to see this reel.

Is there any way I can get the LINK of the reel shared?

Code

let igUsername = "redacted";
let igPassword = "redacted";
const { IgApiClient } = require("instagram-private-api");

async function getLatestPrivateMessages(username, password) {
  const ig = new IgApiClient();

  // Login to Instagram
  ig.state.generateDevice(username);
  await ig.account.login(username, password);

  // Get the current user's inbox
  const inbox = ig.feed.directInbox();
  const threads = await inbox.items();

  // Iterate over the threads and fetch messages
  for (const thread of threads) {
    const { thread_id } = thread;
    const threadFeed = ig.feed.directThread({ thread_id });
    const messages = await threadFeed.items();

    // Process the messages
    for (const message of messages) {
      console.log(message);
    }
  }
}

// Usage
getLatestPrivateMessages(igUsername, igPassword).catch(console.error);

Output


 {
  item_id: 'redacted',
  user_id: redacted,
  timestamp: '1688426164290172',
  item_type: 'placeholder',
  placeholder: [Object: null prototype] {
    is_linked: false,
    title: 'Use Latest App',
    message: 'Use the latest version of the Instagram app to see this reel.',
    reason: 1011
  },
  client_context: 'redacted',
  is_btv_send: false,
  is_ae_dual_send: false,
  show_forward_attribution: false,
  is_shh_mode: false,
  is_sent_by_viewer: false,
  uq_seq_id: 7
}
1alind commented 1 year ago

i use this `let h = JSON.parse(fs.readFileSync('./files/h' + uid + '.json', 'utf8'));

    const response = await axios.get("https://i.instagram.com/api/v1/direct_v2/threads/" + m.message.thread_id + "/get_items/?item_ids=%5B%22" + m.message.item_id + "%22%5D&original_message_client_contexts=%5B%22" + m.message.client_context + "%22%5D", {
      headers: h,
      body: null,
      method: "GET"
    });

var link = response.data.items[0].clip.clip.video_versions[0].url; `

the ( h ) is cookies file from a browser session that i get and add manually ti file since reels are available in browsers ig u can use that and it works fine for me.. just remember to save the session when u login in browser.should be something like this:

{ "accept": "*/*", "accept-language": "en-US,en;q=0.9", "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"Linux\"", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "x-asbd-id": "198387", "x-ig-app-id": "936619743392459", "x-ig-www-claim": "hmac.AR2vqJv-rMUJZ0y3MD6rTCGpFTZHRY8OD0gGoEPuHcCI9jtN", "cookie": "mid=something; ig_did=something; ig_nrcb=1; csrftoken=something; ds_user_id=something; sessionid=something; shbid=\"something\\something\\something\"; shbts=\"something\\something\\something:something\"; rur=\"RVA\\something\\something:something\"", "Referer": "https://www.instagram.com/", "Referrer-Policy": "strict-origin-when-cross-origin" } hope that helps :)

continue47 commented 1 year ago

Thank you @1alind that worked!

Here's an updated code that others might help others:

let igUsername = "";
let igPassword = "";
const { IgApiClient } = require("instagram-private-api");
const axios = require("axios"); // node
async function getLatestPrivateMessages(username, password) {
  const ig = new IgApiClient();

  // Login to Instagram
  ig.state.generateDevice(username);
  await ig.account.login(username, password);

  // Get the current user's inbox
  const inbox = ig.feed.directInbox();
  const threads = await inbox.items();

  // Iterate over the threads and fetch messages
  for (const thread of threads) {
    const { thread_id } = thread;
    const threadFeed = ig.feed.directThread({ thread_id });
    const messages = await threadFeed.items();
    // Process the messages
    for (const message of messages) {
      console.log(message);
      let h = {
        accept: "*/*",
        "accept-language": "en-US,en;q=0.9",
        "sec-ch-ua": '" Not A;Brand";v="99", "Chromium";v="102"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"Linux"',
        "sec-fetch-dest": "empty",
        "sec-fetch-mode": "cors",
        "sec-fetch-site": "same-site",
        "x-asbd-id": "198387",
        "x-ig-app-id": "936619743392459",
        "x-ig-www-claim":
          "hmac.AR2vqJv-rMUJZ0y3MD6rTCGpFTZHRY8OD0gGoEPuHcCI9jtN",
        cookie:
          'INSTA COOKIE',
        Referer: "https://www.instagram.com/",
        "Referrer-Policy": "strict-origin-when-cross-origin",
      };
      const response = await axios.get(
        "https://i.instagram.com/api/v1/direct_v2/threads/" +
          thread_id +
          "/get_items/?item_ids=%5B%22" +
          message.item_id +
          "%22%5D&original_message_client_contexts=%5B%22" +
          message.client_context +
          "%22%5D",
        {
          headers: h,
          body: null,
          method: "GET",
        }
      );
      console.log(response.data.items);
      if (response.data.items[0].item_type == "clip") {
        console.log(response.data.items[0].clip.clip);
      }
    }
  }
}

// Usage
getLatestPrivateMessages(igUsername, igPassword).catch(console.error);
diragb commented 1 year ago

The solution is no longer working, this issue should be reopened @continue47.

continue47 commented 1 year ago

@diragb It's still working for me. Can you share more info about what's not working, what kind of error message do you get, and so on?

Make sure to copy your cookie from instagram into the cookie header in the code (use the developer tools in the browser to go to the network tab and grab the cookie from a request).

diragb commented 1 year ago

How long will the cookie last before we need to update the code @continue47 - any ideas?

diragb commented 1 year ago

For future reference, I'm using this function:

const ig = new IgApiClient()

// Login user and do your stuff..

const getInstagramHeaders = async () => {
  const response = await axios.get('https://www.instagram.com/apple/')
  const html = response.data as string
  const CSRFToken = html.split('csrf_token')[1].split('\\"')[2]
  const IGAppID = html.split('X-IG-App-ID')[1].split(',')[0].replaceAll('"', '').replace(':', '')
  return {
      ...response.headers,
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) 20100101 Firefox/103.0',
      'Accept': '*/*',
      'Accept-Language': 'en,en-US;q=0.3',
      'X-Csrftoken': CSRFToken,
      'X-IG-App-ID': IGAppID,
      'X-ASBD-ID': '198337',
      'X-IG-WWW-Claim': 'hmac.AR2vqJv-rMUJZ0y3MD6rTCGpFTZHRY8OD0gGoEPuHcCI9jtN',
      'Origin': 'https://www.instagram.com',
      'DNT': '1',
      'Alt-Used': 'i.instagram.com',
      'Connection': 'keep-alive',
      'Referer': 'https://www.instagram.com/',
      'Referrer-Policy': 'strict-origin-when-cross-origin',
      'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="102"',
      'sec-ch-ua-mobile': '?0',
      'sec-ch-ua-platform': '"Linux"',
      'Sec-Fetch-Dest': 'empty',
      'Sec-Fetch-Mode': 'cors',
      'Sec-Fetch-Site': 'same-site',
      'Sec-GPC': '1',
      'Cookie': ig.state.cookieJar.getCookieString('https://www.instagram.com')
  }
}
continue47 commented 1 year ago

I don't know how much the cookie lasts, it doesn't need to last that long for my use case.