Skip to content

Instantly share code, notes, and snippets.

@ZipFile
Last active September 18, 2023 16:03
Star You must be signed in to star a gist
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()
@dnslin
Copy link

dnslin commented Jul 25, 2022

@dnslin这种类型的流程,可以在身份鉴别器中使用。

@Kevin-2106如果是这样,立即更新并指向您的pixiv-nginx代理代理。或者,使用代理代理(见)。LOGIN_URL``AUTH_TOKEN_URL

Thank you very much

@Kevin-2106
Copy link

@Kevin-2106 I do not know how pixiv-nginx works, better ask the devs whether it proxies private apis used by andoid/ios app. If it does, just update LOGIN_URL and AUTH_TOKEN_URL to point to your reverse proxy. Or alternatively, use regular proxy (see discussion above).

Solved. I've installed a certificate and edited Hosts to access pixiv.net through 127.0.0.1 , while requests can't verify the certificate and raised an SSL Error.
To solve it, just add "verify=False" to requests.post(), then the code should be:
解决了。我为了直接访问pixiv改了hosts,安装了证书,但是requests不能验证我的证书于是抛出了SSL Error,解决方法是在requests.post()中增加"verify=False"。改后代码如下。

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,
            "app-os-version": "14.6",
            "app-os": "ios",
        },
        verify=False,
        **REQUESTS_KWARGS
    )

Thanks anyway!

@EnderAvaritia
Copy link

i think i full the token truely
image
but it can't work
image

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