diff --git a/docs/configuration.rst b/docs/configuration.rst index 88dfe116..71067992 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -230,6 +230,7 @@ Description The username and password to use when attempting to log in to * ``e621`` * ``exhentai`` * ``idolcomplex`` + * ``instagram`` * ``luscious`` * ``sankaku`` * ``tsumino`` diff --git a/docs/supportedsites.rst b/docs/supportedsites.rst index 83e9bd74..b564f52a 100644 --- a/docs/supportedsites.rst +++ b/docs/supportedsites.rst @@ -59,7 +59,7 @@ ImgBB https://imgbb.com/ Albums, individual Imag imgbox https://imgbox.com/ Galleries, individual Images imgth https://imgth.com/ Galleries imgur https://imgur.com/ |imgur-C| -Instagram https://www.instagram.com/ |instagram-C| +Instagram https://www.instagram.com/ |instagram-C| Optional Issuu https://issuu.com/ Publications, User Profiles Jaimini's Box https://jaiminisbox.com/reader/ Chapters, Manga Joyreactor http://joyreactor.com/ Posts, Search Results, Tag Searches, User Profiles diff --git a/gallery_dl/extractor/instagram.py b/gallery_dl/extractor/instagram.py index 7fa5d32e..37817118 100644 --- a/gallery_dl/extractor/instagram.py +++ b/gallery_dl/extractor/instagram.py @@ -10,10 +10,11 @@ """Extractors for https://www.instagram.com/""" from .common import Extractor, Message -from .. import text +from .. import text, exception from ..cache import cache import itertools import json +import time import re @@ -66,10 +67,36 @@ class InstagramExtractor(Extractor): @cache(maxage=360*24*3600, keyarg=1) def _login_impl(self, username, password): - self.log.warning( - 'Logging in with username and password is currently not possible. ' - 'Use cookies from your browser session instead.') - return {} + self.log.info("Logging in as %s", username) + + page = self.request(self.root + "/accounts/login/").text + headers = { + "Referer" : self.root + "/accounts/login/", + "X-IG-App-ID" : "936619743392459", + "X-Requested-With": "XMLHttpRequest", + } + + response = self.request(self.root + "/web/__mid/", headers=headers) + headers["X-CSRFToken"] = response.cookies["csrftoken"] + headers["X-Instagram-AJAX"] = text.extract( + page, '"rollout_hash":"', '"')[0] + + url = self.root + "/accounts/login/ajax/" + data = { + "username" : username, + "enc_password" : "#PWD_INSTAGRAM_BROWSER:0:{}:{}".format( + int(time.time()), password), + "queryParams" : "{}", + "optIntoOneTap": "false", + } + response = self.request(url, method="POST", headers=headers, data=data) + + if not response.json().get("authenticated"): + raise exception.AuthenticationError() + return { + key: self.session.cookies.get(key) + for key in ("sessionid", "mid", "csrftoken") + } def _request_graphql(self, variables, query_hash, csrf=None): headers = { diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py index 8dabbc70..1adfb8de 100755 --- a/scripts/supportedsites.py +++ b/scripts/supportedsites.py @@ -151,6 +151,7 @@ AUTH_MAP = { "flickr" : "Optional (OAuth)", "idolcomplex": "Optional", "imgbb" : "Optional", + "instagram" : "Optional", "mangoxo" : "Optional", "newgrounds" : "Optional", "nijie" : "Required",