pgrimaud/instagram-user-feed

Trying login but always return response "Unable to extract JSON data"

sportakal opened this issue · 12 comments

Version(s) affected: 6.16

Description
When I try to login with Instagram::withCredentials() and ->login() method with username and password, I keep getting this error "Unable to extract JSON data". Everything was working fine yesterday, today it suddenly started giving this error constantly.

How to reproduce

$instagram = Instagram::withCredentials(
            new \GuzzleHttp\Client(array_merge([
                'verify' => false,
            ])), $this->account->username, $this->account->password, $this->cache_manager
        );

        $instagram = $instagram->login();

Possible Solution
The error occurs at here, Instagram\Auth\Login.php içerisinde, preg_match('/<script type="text\/javascript">window\._sharedData\s?=(.+);<\/script>/', $html, $matches);

This function, makes a request to https://instagram.com to get initial cookies. When i make a request to https://instagram.com via postman, i didn't find any tag that is <script type="text/javascript">window._sharedData....

I think there is something changed on instagram. Has anyone encountered this problem?

I am continuing to research.

An error occured at returning as a result of the request to get the csrf_cookie from Instagram.

It will be necessary to update the function that receives the csrf_cookie. Because now Instagram has embedded it in <script>requireLazy(["JSScheduler...</script>. From here we need to extract the json containing the csrf_token.

I also checked the code and I found out that the following code is not able to open the base URL of Instagram... Instagram throws the error link is broken

And the Tag is also missing that @sportakal mentioned

$baseRequest = $this->client->request('GET', InstagramHelper::URL_BASE, [
            'headers' => [
                'user-agent' => OptionHelper::$USER_AGENT,
            ],
        ]);

Instagram has done some major changes and now the CSRF token is present in
<script>requireLazy(["JSScheduler","ServerJS","ScheduledApplyEach"] ....... </script>

image

How we can get csrf again? Do you have any idea?

I found a way;

Use this
preg_match('/\\\"csrf_token\\\":\\\"(.*?)\\\"/', $html, $matches);
instead of
preg_match('/<script type="text\/javascript">window\._sharedData\s?=(.+);<\/script>/', $html, $matches);
at Login.php:73

This gets csrf_token as variable $matches[1]
$csrf_token = $matches[1]
Then use in try/catch block

$query = $this->client->request('POST', InstagramHelper::URL_AUTH, [
                'form_params' => [
                    'username' => $this->login,
                    'enc_password' => '#PWD_INSTAGRAM_BROWSER:0:' . time() . ':' . $this->password,
                ],
                'headers' => [
                    'cookie' => 'ig_cb=1; csrftoken=' . $csrf_cookie,
                    'referer' => InstagramHelper::URL_BASE,
                    'x-csrftoken' => $csrf_cookie,
                    'user-agent' => OptionHelper::$USER_AGENT,
                    'accept-language' => OptionHelper::$LOCALE,
                ],
                'cookies' => $cookieJar,
            ]);

It worked for me.

@sportakal Nice it solves the issues.

- can you mark it as a bug instead of need investigations

For those who are facing error during like unlike then

open your AbstractDataFeed.php file and change your code on lines 125 & 131

image

I've tried both combinations suggested for AbstractDataFeed.php and Login.php
But keep getting error:

Unknown error, please report it with a GitHub issue. Client error: POST https://www.instagram.com/accounts/login/ajax/ resulted in a 403 Forbidden

And a not login html page response.

I've tried both combinations suggested for AbstractDataFeed.php and Login.php But keep getting error:

Unknown error, please report it with a GitHub issue. Client error: POST https://www.instagram.com/accounts/login/ajax/ resulted in a 403 Forbidden

And a not login html page response.

What you need to do, is to logout from the web browser and request a password reset. That will tell you that they noticed some unusual activity and they will need you to verify your account. You wont need to change your password but the account will then be unblocked. However you can still not use the password to login using this package since the account will get blocked immediately. Maybe using a proxy will temporarily solve this issue but it will ultimately come back.

What I do now, after using the fixes in the posts above, is to login from the web browser and use that cookie to login using the loginWithCookies method from this package. You can use Chrome dev console to see the sessionid and the expires date. Here is an example that works:

$api = new Api();
    $cookie = new \GuzzleHttp\Cookie\SetCookie([
   "Name"     => "sessionid",
   "Value"    => "your_sessionid",
   "Domain"   => ".instagram.com",
   "Path"     => "/",
   "Expires"  => "your_expires_date_in_utc_format",
   "Max-Age"  => "31536000",
   "Secure"   => true,
   "Discard"  => false,
   "HttpOnly" => true,
]);
$cookieJar = new CookieJar(false, [$cookie]);           
$api->loginWithCookies($cookieJar);

However this method is also unreliable. It might work for some hours but then I receive a syntax error.

About that error, using a proxy solves it but comes back again after some hours. Generally I dont think that this package works anymore at its current state. Some modifications are needed. I will look into it when I have time and maybe I can come up with a solution.

I believe real reason you need to post password some kind of encryipted. Haven't found what kind of is

I believe real reason you need to post password some kind of encryipted. Haven't found what kind of is

in Login.php on line 87:

'enc_password' => '#PWD_INSTAGRAM_BROWSER:0:' . time() . ':' . $this->password,

However, I think I figured out a way to use the existing set of cookies from a web browser with this package and keep you logged in without getting syntax error. You just put all the cookies from the web browser in the cookieJar as well as set the user agent. Mind the single quotes on some of the values. Also, for the sake of validity, change my "Expires" dates to your own:

$api = new Api();
            $api->setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.57 Safari/537.36');
            $cookie = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "csrftoken",
                "Value"    => "your_csrftoken",
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2023-11-04T21:42:50.882Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie2 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "sessionid",
                "Value"    => "your_sessionid",
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2023-11-05T21:42:43.699Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie3 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "shbts",
                "Value"    => '"your_shbts"',
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2022-11-12T21:42:12.314Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie4 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "shbid",
                "Value"    => '"your_shbid"',
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2022-11-12T21:42:12.314Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie5 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "datr",
                "Value"    => "your_datr",
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2024-07-31T10:12:04.896Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie6 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "ds_user_id",
                "Value"    => "your_ds_user_id",
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2023-02-03T21:42:50.882Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie7 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "ig_did",
                "Value"    => "your_ig_did",
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2024-05-11T13:09:22.194Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookie8 = new \GuzzleHttp\Cookie\SetCookie([
                "Name"     => "dpr",
                "Value"    => "your_dpr",
                "Domain"   => ".instagram.com",
                "Path"     => "/",
                "Expires"  => "2022-11-12T21:42:46.000Z",
                "Max-Age"  => "31536000",
                "Secure"   => true,
                "Discard"  => false,
                "HttpOnly" => true,
            ]);

            $cookieJar = new CookieJar(false, [$cookie, $cookie2, $cookie3, $cookie4, $cookie5, $cookie6, $cookie7, $cookie8]);           
            $api->loginWithCookies($cookieJar);       
            $profile = $api->getProfile(env('INSTAGRAM_PROFILE'));

Then thing is that I don't know what really fixed the issue:

Sending the user agent
or
Setting the cookies

But this will now work for a year before need changing.

Hello,
I can confirm the same happens to me. "Unknown error, please report it with a GitHub issue" and then when using @m33ts4k0z method I receive "Please login with instagram credentials."

Could it be related to MFA?
For me, the lib is unusable now

@JasonBenett I personally stopped using this package because it was too much of a hassle and a maintenance nightmare. Since I had control over the account I wanted to display, I used the API way and I have forgotten about it. I refresh the token once every 2 months with a crontjob and everything just works on its own.