Instagram-private-api: How to store user session in v1

Created on 29 Apr 2019  路  17Comments  路  Source: dilame/instagram-private-api

Hello and thanks for that awesome library!

I'm building a simple chat bot software.
The application performs some operations in the background.

Is it possible to store user session somehow for my REST API (preferably in the database) so the application will not need to perform the instagram login flow every time?

Most helpful comment

In addition you should save device data. Explore it in core/state.ts

Which device data should I save? I can see a lot of fields in the generateDevice method.
And how I should restore it? Should I just reassign proper fields?

It is your choice what fields to save, but i recommend at least save all the fields that generateDevice generates.
To restore it you have to just reassign it.

When you are restoring it you don't have to call generateDevice()

BTW will be good if someone could help me with docs, i don't have enough time for everything

All 17 comments

id like to know this as well

@dilame does it mean the new version, everytime i call the login, it does the entire login workflow?
If I save the cookie & device objects into the database how can I avoid the login?
I am experiencing a strange issue: IG this morning asked me to login into the app and I was thinking if it could be related to the fact that I am doing login everytime I execute some automations

In addition you should save device data. Explore it in core/state.ts

Which device data should I save? I can see a lot of fields in the generateDevice method.
And how I should restore it? Should I just reassign proper fields?

@alexgiul I think you should call

// In order to restore session cookies you need this await ig.state.deserializeCookieJar(JSON.stringify(cookies));

with your serialized cookie string.

Thus you'll bypass extra login flows.

@dilame does it mean the new version, everytime i call the login, it does the entire login workflow?
If I save the cookie & device objects into the database how can I avoid the login?
I am experiencing a strange issue: IG this morning asked me to login into the app and I was thinking if it could be related to the fact that I am doing login everytime I execute some automations

You can avoid the login by just restoring ig.state. You only need to login once and save all the needed data in your persistent storage.

In addition you should save device data. Explore it in core/state.ts

Which device data should I save? I can see a lot of fields in the generateDevice method.
And how I should restore it? Should I just reassign proper fields?

It is your choice what fields to save, but i recommend at least save all the fields that generateDevice generates.
To restore it you have to just reassign it.

When you are restoring it you don't have to call generateDevice()

BTW will be good if someone could help me with docs, i don't have enough time for everything

Hello,

I'm trying to migrate few cli tools I used to have with pre-1.0 version. Lots of change but much cleaner functions ! Thanks for this work.

So If I understand correctly we can deserialize the cookie and load it. As for the other state infos, I guess we should simply save the infos generated by generateDevice function : https://github.com/dilame/instagram-private-api/blob/master/src/core/state.ts#L175

This means:

{
  deviceString
  deviceId
  uuid
  phoneId
  adid
  build
}

Should be saved and restored. Let's try then !

Ok, here is my little functionnal code for those who'd like to login once and then use the device + cookie :

;(async () => {
  const ig = new IgApiClient()
  ig.state.generateDevice(config.auth.user)
  // ig.state.device
  try {
    if (fs.existsSync(`${userCookiePath}`) && fs.existsSync(`${userDevicePath}`)) {
      console.log('loading device and session from disk...')
      let savedCookie = fs.readFileSync(userCookiePath, 'utf-8')
      let savedDevice = JSON.parse(fs.readFileSync(userDevicePath), 'utf-8')
      await ig.state.deserializeCookieJar(savedCookie)
      ig.state.deviceString = savedDevice.deviceString
      ig.state.deviceId = savedDevice.deviceId
      ig.state.uuid = savedDevice.uuid
      ig.state.adid = savedDevice.adid
      ig.state.build = savedDevice.build
      let pk = await ig.user.getIdByUsername(config.auth.user)
      await listFollowers(pk)
    } else {
      Bluebird.try(async () => {
        const auth = await ig.account.login(config.auth.user, config.auth.password)
        const cookieJar = await ig.state.serializeCookieJar()
        fs.writeFileSync(userCookiePath, JSON.stringify(cookieJar), 'utf-8')
        let device = (({ deviceString, deviceId, uuid, adid, build }) => ({ deviceString, deviceId, uuid, adid, build }))(ig.state)
        fs.writeFileSync(userDevicePath, JSON.stringify(device), 'utf-8')
        await listFollowers(auth.pk)
      }).catch(IgCheckpointError, async () => {
        console.log(ig.state.checkpoint) // Checkpoint info here
        await ig.challenge.auto(true) // Requesting sms-code or click "It was me" button
        console.log(ig.state.checkpoint) // Challenge info here
        const { code } = await inquirer.prompt([
          {
            type: 'input',
            name: 'code',
            message: 'Enter code'
          }
        ])
        await ig.challenge.sendSecurityCode(code)
        await ig.account.login(config.auth.user, config.auth.password)
      })
    }
  } catch (err) {
    console.error(err)
  }
})()

So far it works !

I'm not really happy with device loading part. I think we should have a loadDevice method and maybe better / easier a loadState() method. What do you think @dilame

I'm not really happy with device loading part. I think we should have a loadDevice method and maybe better / easier a loadState() method. What do you think @dilame

It would be nice if we could write loadDevice or loadState methods that would satisfy everyone's requirement. I wanted to implement it, but stucked into too much variations. If you can propose something good - you are welcome. But, please, remember that your use-case is totally different from my use-case, so the proposal must be flexible enough to satisfy both.

Ok, here is my little functionnal code for those who'd like to login once and then use the device + cookie :

;(async () => {
  const ig = new IgApiClient()
  ig.state.generateDevice(config.auth.user)
  // ig.state.device
  try {
    if (fs.existsSync(`${userCookiePath}`) && fs.existsSync(`${userDevicePath}`)) {
      console.log('loading device and session from disk...')
      let savedCookie = fs.readFileSync(userCookiePath, 'utf-8')
      let savedDevice = JSON.parse(fs.readFileSync(userDevicePath), 'utf-8')
      await ig.state.deserializeCookieJar(savedCookie)
      ig.state.deviceString = savedDevice.deviceString
      ig.state.deviceId = savedDevice.deviceId
      ig.state.uuid = savedDevice.uuid
      ig.state.adid = savedDevice.adid
      ig.state.build = savedDevice.build
      let pk = await ig.user.getIdByUsername(config.auth.user)
      await listFollowers(pk)
    } else {
      Bluebird.try(async () => {
        const auth = await ig.account.login(config.auth.user, config.auth.password)
        const cookieJar = await ig.state.serializeCookieJar()
        fs.writeFileSync(userCookiePath, JSON.stringify(cookieJar), 'utf-8')
        let device = (({ deviceString, deviceId, uuid, adid, build }) => ({ deviceString, deviceId, uuid, adid, build }))(ig.state)
        fs.writeFileSync(userDevicePath, JSON.stringify(device), 'utf-8')
        await listFollowers(auth.pk)
      }).catch(IgCheckpointError, async () => {
        console.log(ig.state.checkpoint) // Checkpoint info here
        await ig.challenge.auto(true) // Requesting sms-code or click "It was me" button
        console.log(ig.state.checkpoint) // Challenge info here
        const { code } = await inquirer.prompt([
          {
            type: 'input',
            name: 'code',
            message: 'Enter code'
          }
        ])
        await ig.challenge.sendSecurityCode(code)
        await ig.account.login(config.auth.user, config.auth.password)
      })
    }
  } catch (err) {
    console.error(err)
  }
})()

So far it works !

It works for you but I still get "requires login" error 馃槩馃槶馃槶

I'm experiencing the same thing, did anyone get a working example?

experiencing the requires login error too

Everyone has a different need. What does not "work". As stated by @dilame my needs with loadstate is different from his and probably from yours. Did you tried : https://github.com/dilame/instagram-private-api/issues/732#issuecomment-498624236

i'm having the following problem :
IgLoginRequiredError: GET /api/v1/users/search/?timezone_offset=3600&q=cristiano&count=30 - 403 Forbidden; login_required

Reset your session

Was this page helpful?
0 / 5 - 0 ratings

Related issues

theonlygusti picture theonlygusti  路  11Comments

ciolt picture ciolt  路  35Comments

dhillon2325 picture dhillon2325  路  14Comments

codingzombies picture codingzombies  路  19Comments

endquote picture endquote  路  12Comments