Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exceptions in case Instagram asks to enter recaptcha or phone number #757

Merged
merged 11 commits into from
Aug 26, 2020
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace InstagramScraper\Exception;

class InstagramChallengeRecaptchaException extends InstagramException
{
public function __construct($message = "", $code = 400, $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace InstagramScraper\Exception;

class InstagramChallengeSubmitPhoneNumberException extends InstagramException
{
public function __construct($message = "", $code = 400, $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
28 changes: 23 additions & 5 deletions src/InstagramScraper/Instagram.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Exception;
use InstagramScraper\Exception\InstagramAuthException;
use InstagramScraper\Exception\InstagramChallengeRecaptchaException;
use InstagramScraper\Exception\InstagramChallengeSubmitPhoneNumberException;
use InstagramScraper\Exception\InstagramException;
use InstagramScraper\Exception\InstagramNotFoundException;
use InstagramScraper\Exception\InstagramAgeRestrictedException;
Expand Down Expand Up @@ -1623,9 +1625,11 @@ public function getStories($reel_ids = null)
* $support_two_step_verification true works only in cli mode - just run login in cli mode - save cookie to file and use in any mode
*
* @return array
* @throws InstagramException
*
* @throws InstagramAuthException
* @throws InstagramChallengeRecaptchaException
* @throws InstagramChallengeSubmitPhoneNumberException
* @throws InstagramException
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function login($force = false, $twoStepVerificator = null)
{
Expand Down Expand Up @@ -1672,7 +1676,6 @@ public function login($force = false, $twoStepVerificator = null)
$response->code === static::HTTP_BAD_REQUEST
&& isset($response->body->message)
&& $response->body->message == 'checkpoint_required'
&& !empty($twoStepVerificator)
) {
$response = $this->verifyTwoStep($response, $cookies, $twoStepVerificator);
} elseif ((is_string($response->code) || is_numeric($response->code)) && is_string($response->body)) {
Expand Down Expand Up @@ -1741,11 +1744,14 @@ public function isLoggedIn($session)
/**
* @param $response
* @param $cookies
* @param TwoStepVerificationInterface $twoStepVerificator
* @param TwoStepVerificationInterface|null $twoStepVerificator
*
* @return Response
* @throws InstagramAuthException
* @throws InstagramChallengeRecaptchaException
* @throws InstagramChallengeSubmitPhoneNumberException
*/
private function verifyTwoStep($response, $cookies, $twoStepVerificator)
private function verifyTwoStep($response, $cookies, TwoStepVerificationInterface $twoStepVerificator = null)
{
$new_cookies = $this->parseCookies($response->headers);
$cookies = array_merge($cookies, $new_cookies);
Expand All @@ -1762,6 +1768,18 @@ private function verifyTwoStep($response, $cookies, $twoStepVerificator)

$url = Endpoints::BASE_URL . $response->body->checkpoint_url;
$response = Request::get($url, $headers);

if (preg_match('/"challengeType":"RecaptchaChallengeForm"/', $response->raw_body, $matches)) {
throw new InstagramChallengeRecaptchaException('Instagram asked to enter the captcha.', $response->code);
} elseif (preg_match('/"challengeType":"SubmitPhoneNumberForm"/', $response->raw_body, $matches)) {
throw new InstagramChallengeSubmitPhoneNumberException('Instagram asked to enter a phone number.', $response->code);
}

// for 2FA case
if (! $twoStepVerificator instanceof TwoStepVerificationInterface) {
throw new InstagramAuthException('$twoStepVerificator must be an instance of TwoStepVerificationInterface.', $response->code);
}

if (preg_match('/window._sharedData\s\=\s(.*?)\;<\/script>/', $response->raw_body, $matches)) {
$data = json_decode($matches[1], true, 512, JSON_BIGINT_AS_STRING);
if (!empty($data['entry_data']['Challenge'][0]['extraData']['content'][3]['fields'][0]['values'])) {
Expand Down