Skip to content

Instantly share code, notes, and snippets.

@ZipFile

ZipFile/README.md

Last active Jun 12, 2021
Embed
What would you like to do?
Pixiv OAuth Flow

Retrieving Auth Token

  1. Run the command:

    python pixiv_auth.py login

    This will open the browser with Pixiv login page.

  2. Open dev console (F12) and switch to network tab.

  3. Enable persistent logging ("Preserve log").

  4. Type into the filter field: callback?

  5. Proceed with Pixiv login.

  6. After logging in you should see a blank page and request that looks like this: https://app-api.pixiv.net/web/v1/users/auth/pixiv/callback?state=...&code=.... Copy value of the code param into the pixiv_auth.py's prompt and hit the Enter key.

If you did everything right and Pixiv did not change their auth flow, pair of auth_token and refresh_token should be displayed.

⚠️ code's lifetime is extremely short, so make sure to minimize delay between step 5 and 6. Otherwise, repeat everything starting step 1.

Refresh Tokens

python pixiv_auth.py refresh OLD_REFRESH_TOKEN
#!/usr/bin/env python
from argparse import ArgumentParser
from base64 import urlsafe_b64encode
from hashlib import sha256
from pprint import pprint
from secrets import token_urlsafe
from sys import exit
from urllib.parse import urlencode
from webbrowser import open as open_url
import requests
# Latest app version can be found using GET /v1/application-info/android
USER_AGENT = "PixivAndroidApp/5.0.234 (Android 11; Pixel 5)"
REDIRECT_URI = "https://app-api.pixiv.net/web/v1/users/auth/pixiv/callback"
LOGIN_URL = "https://app-api.pixiv.net/web/v1/login"
AUTH_TOKEN_URL = "https://oauth.secure.pixiv.net/auth/token"
CLIENT_ID = "MOBrBDS8blbauoSck0ZfDbtuzpyT"
CLIENT_SECRET = "lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj"
def s256(data):
"""S256 transformation method."""
return urlsafe_b64encode(sha256(data).digest()).rstrip(b"=").decode("ascii")
def oauth_pkce(transform):
"""Proof Key for Code Exchange by OAuth Public Clients (RFC7636)."""
code_verifier = token_urlsafe(32)
code_challenge = transform(code_verifier.encode("ascii"))
return code_verifier, code_challenge
def print_auth_token_response(response):
data = response.json()
try:
access_token = data["access_token"]
refresh_token = data["refresh_token"]
except KeyError:
print("error:")
pprint(data)
exit(1)
print("access_token:", access_token)
print("refresh_token:", refresh_token)
print("expires_in:", data.get("expires_in", 0))
def login():
code_verifier, code_challenge = oauth_pkce(s256)
login_params = {
"code_challenge": code_challenge,
"code_challenge_method": "S256",
"client": "pixiv-android",
}
open_url(f"{LOGIN_URL}?{urlencode(login_params)}")
try:
code = input("code: ").strip()
except (EOFError, KeyboardInterrupt):
return
response = requests.post(
AUTH_TOKEN_URL,
data={
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"code": code,
"code_verifier": code_verifier,
"grant_type": "authorization_code",
"include_policy": "true",
"redirect_uri": REDIRECT_URI,
},
headers={"User-Agent": USER_AGENT},
)
print_auth_token_response(response)
def refresh(refresh_token):
response = requests.post(
AUTH_TOKEN_URL,
data={
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"grant_type": "refresh_token",
"include_policy": "true",
"refresh_token": refresh_token,
},
headers={"User-Agent": USER_AGENT},
)
print_auth_token_response(response)
def main():
parser = ArgumentParser()
subparsers = parser.add_subparsers()
parser.set_defaults(func=lambda _: parser.print_usage())
login_parser = subparsers.add_parser("login")
login_parser.set_defaults(func=lambda _: login())
refresh_parser = subparsers.add_parser("refresh")
refresh_parser.add_argument("refresh_token")
refresh_parser.set_defaults(func=lambda ns: refresh(ns.refresh_token))
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
main()
@upbit

This comment has been minimized.

Copy link

@upbit upbit commented Feb 15, 2021

Thank you very much for this script, this is currently the easiest way to get OAuth2 token.
Open the chrome network tab and click login. The last red url contains code:

@emesh0620

This comment has been minimized.

Copy link

@emesh0620 emesh0620 commented Feb 16, 2021

Thank you very much. I couldn't log in temporarily,
but I copied and pasted the source code and it worked.
It's a shame that I can't really log in with a password, but I found some hope.

@Xpl0itR

This comment has been minimized.

Copy link

@Xpl0itR Xpl0itR commented Feb 16, 2021

Works perfect 👌 thanks

@shibababa

This comment has been minimized.

Copy link

@shibababa shibababa commented Feb 16, 2021

great.
That was a really big help.
thanks.

@Xpl0itR

This comment has been minimized.

Copy link

@Xpl0itR Xpl0itR commented Feb 16, 2021

One criticism i have is that instead of printing expires_in you should instead print the timestamp of when it expires

@TakaShirowa

This comment has been minimized.

Copy link

@TakaShirowa TakaShirowa commented Feb 19, 2021

requests.exceptions.SSLError: HTTPSConnectionPool(host='oauth.secure.pixiv.net', port=443): Max retries exceeded with url: /auth/token (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1122)')
))
I keep reporting this error, is it problem to the network?

@bakashigure

This comment has been minimized.

Copy link

@bakashigure bakashigure commented Feb 19, 2021

requests.exceptions.SSLError: HTTPSConnectionPool(host='oauth.secure.pixiv.net', port=443): Max retries exceeded with url: /auth/token (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1122)')
))
I keep reporting this error, is it problem to the network?

add proxy here
3%{((EE}%}%CCCUPZ2CJ0

@TakaShirowa

This comment has been minimized.

Copy link

@TakaShirowa TakaShirowa commented Feb 19, 2021

requests.exceptions.SSLError:HTTPSConnectionPool(host ='oauth.secure.pixiv.net',端口= 443):url超过了最大重试次数:/ auth / token(由SSLError(SSLError(1,'[SSL:WRONG_VERSION_NUMBER]版本号错误(_ssl.c:1122)')
))
我一直在报告此错误,这对网络有问题吗?

在此处添加代理
3%{(((EE}%}%CCCUPZ2CJ0

Problem solved, thank you

@Cai-Zhenhui

This comment has been minimized.

Copy link

@Cai-Zhenhui Cai-Zhenhui commented Mar 8, 2021

After I get the Code and input it, the following exception is thrown:
File ".\pixiv_auth.py", line 69, in login response = requests.post( ... File "C:\Users\MACHENIKE\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\adapters.py", line 498, in send raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))
How should I do?

@railannad

This comment has been minimized.

Copy link

@railannad railannad commented Mar 9, 2021

My Python Version is 3.8.0 and how should I do?
image

@ZipFile

This comment has been minimized.

Copy link
Owner Author

@ZipFile ZipFile commented Mar 9, 2021

@Cai-Zhenhui check your connection to pixiv. Maybe you need a proxy, as suggested by bakashigure above.

@railannad this message appears when your code is invalid, expired or was already used. Try again.

@railannad

This comment has been minimized.

Copy link

@railannad railannad commented Mar 9, 2021

@Cai-Zhenhui check your connection to pixiv. Maybe you need a proxy, as suggested by bakashigure above.

@railannad this message appears when your code is invalid, expired or was already used. Try again.

I tried again and successed . Thank you very much

@koitoyuu19

This comment has been minimized.

Copy link

@koitoyuu19 koitoyuu19 commented Mar 10, 2021

After I input Code and hit the enter key, nothing display. So I add proxy 127.0.0.1:7890,but it shows like this. Could you help me ? please.
7RC4%JQNV}0BZP VXU~D K3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment