gppt: get-pixivpy-token
- Get your Pixiv token (for running upbit/pixivpy)
- Refine pixiv_auth.py + its fork
Install
pip install gppt
Usage
gppt has two commands: configure stores an account in a profile, login gets you a token.
# Configure a profile (writes to: ~/.config/gppt/<profile>.json by default)
gppt configure
# Log in (writes to: ~/.config/gppt/<profile>.token.json by default)
gppt login
~/.config/gppt/<profile>.json:
{
"username": "<plain username or op:// link>",
"password": "<plain password or op:// link>",
"totp_secret": "<base32 secret, otpauth:// URI, or op:// link>",
"auth_method": "e2e" // or "oauth"
}
~/.config/gppt/<profile>.token.json:
{
"access_token": "***",
"refresh_token": "***",
"expires_in": 3600,
"expires_at": "2026-08-08T16:34:57.776005+00:00",
"user_id": "***",
"user_name": "***",
"user_account": "***"
}
Two-factor authentication
If your account has 2FA enabled, pixiv asks for a verification code after the
password. With the e2e method gppt fills it in from totp_secret — the
base32 secret pixiv shows you when you set up an authenticator app, the
otpauth:// URI behind its QR code, or an op:// reference to either. This is
what makes an unattended headless login possible on a 2FA account.
Leave totp_secret blank and gppt login prompts for a code on stdin instead,
only when pixiv actually asks for one. Accounts without 2FA are unaffected.
None of this applies to the oauth method: you are in your own browser, so
pixiv's 2FA prompt is just part of the login you are doing by hand.
Environment variables
| Variable | Effect |
|---|---|
GPPT_USERNAME, GPPT_PASSWORD, GPPT_TOTP_SECRET |
Override the profile's credentials — lets a container or CI job log in with no config file |
GPPT_AUTH_METHOD |
Override the profile's authentication method (e2e or oauth) |
GPPT_CONFIG_DIR |
Directory holding profiles and cached tokens (default: $XDG_CONFIG_HOME/gppt) |
ALL_PROXY, HTTPS_PROXY, HTTP_PROXY |
Proxy used by both the browser and the token requests |
From Python
gppt.get_token() is the library form of gppt login: it reuses the cached
token, refreshes it, or logs in — by the profile's method — if needed.
import gppt
from pixivpy3 import AppPixivAPI
token = gppt.get_token() # profile "default", configured with `gppt configure`
aapi = AppPixivAPI()
aapi.auth(refresh_token=token.refresh_token)
It is silent by default; pass notify=print to see the same progress messages
the CLI writes.
gppt.oauth_login() is the OAuth2 PKCE flow as a library call — it prints the
login URL, opens it, and reads the pasted code from stdin. No credentials, no
files:
token = gppt.oauth_login()
Point it at your own UI with prompt= and notify=, and pass open_browser=False to only print the URL.
For a one-off login that reads and writes nothing on disk, use gppt.login():
token = gppt.login(username="...", password="...")
token.access_token, token.refresh_token, token.expires_in
For a 2FA account, pass the TOTP secret — or a totp_prompt callable that is
invoked only if pixiv asks for a code:
token = gppt.login("...", "...", "JBSWY3DPEHPK3PXP")
token = gppt.login("...", "...", totp_prompt=lambda: input("code: "))
And gppt.refresh() exchanges a refresh token you are storing yourself:
token = gppt.refresh("...")
| Name | Purpose |
|---|---|
gppt.get_token(profile="default", *, method=None, headless=True, force=False, save=True, notify=None, totp_prompt=None) |
A valid token for a stored profile, logging in only if needed. method is "e2e", "oauth", or None for whatever the profile says |
gppt.login(username="", password="", totp_secret="", *, headless=None, totp_prompt=None) |
One browser login; no files touched |
gppt.oauth_login(*, open_browser=True, prompt=None, notify=None) |
One OAuth2 PKCE login — you paste the code; no files touched |
gppt.refresh(refresh_token) |
Refresh token → new token |
gppt.Token |
Result dataclass: access_token, refresh_token, expires_in, expires_at, is_expired, user_id, user_name, user_account |
gppt.LoginError, gppt.TokenError |
Raised when a login yields no authorization code / pixiv rejects the request |
Metadata
Release files for gppt 5.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gppt-5.1.0.tar.gz | 20.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gppt-5.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.3 kB
Release files / gppt-5.1.0.tar.gz
| Download URL | gppt-5.1.0.tar.gz |
|---|---|
| Size | 20.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00ad18f7139d00f260496dc630ce7a7c9bff404eea47d646365ee4f1f2c676e3
|
|
BLAKE2b-256 checksum How to use checksums |
9db78cf341892aee160cdb732cca4c7aa8959622c933ade27efd57a8c7185522
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / gppt-5.1.0-py3-none-any.whl
| Download URL | gppt-5.1.0-py3-none-any.whl |
|---|---|
| Size | 24.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6eefee83ada3423ef7e53c5ae54501c0eb26a4d1f65b26f6dfff76f250d43194
|
|
BLAKE2b-256 checksum How to use checksums |
af147fdcb61e18a5f8c7395b480f78f4f837f109b705dce239c61ae98f5c5fb2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|