Fetch Pixiv OAuth access/refresh tokens via stealth browser automation, with multi-account cache and auto refresh.
Project description
Pixiv OAuth Token Fetcher
A Python automation tool that simulates Pixiv OAuth login, captures the authorization code, and exchanges it for an access token.
📦 Features
- ✅ Automated Pixiv login (username/password)
- ✅ Headless mode support
- ✅ Visible (non-headless) mode support
- ✅ Console-based authorization code capture via CDP
- ✅ Access token & refresh token retrieval
- ✅ Slow typing to bypass bot detection
- ✅ Auto-skip security prompt pages (Passkeys / 2FA reminders)
- ✅ Multi-selector fallback for Pixiv login form compatibility
- ✅ Token cache + auto refresh (browser login only on first run / when refresh token expires)
- ✅ Multi-account support (one cache file per email under
~/.pixiv-token/) - ✅ Machine-readable output (
--json,--print <field>) — result on stdout, logs on stderr - ✅ Standard
loggingintegration — library is silent by default; consumers configure their own handlers - ✅ Installable as a library (
pip install .) and CLI (pixiv-token)
🚀 Installation
1. Clone the repository
git clone https://github.com/piglig/pixiv-token.git
cd pixiv-token
2. Install dependencies
Recommended Python version: >=3.8
# As a dev checkout
pip install -r requirements.txt
# Or install as a package (exposes the `pixiv-token` CLI)
pip install .
⚙️ Usage
Command line
# First run for an account — credentials required, browser login performed and token cached
python pixiv_token_fetcher.py -u "your_email" -p "your_password"
# Subsequent runs — cache is used; if expired, refresh_token is used automatically
# (auto-selected when only one account is cached)
python pixiv_token_fetcher.py
# Multiple accounts — select which cached account to use
python pixiv_token_fetcher.py --account "your_email"
# List all cached accounts and their expiry
python pixiv_token_fetcher.py --list-accounts
# Visible browser mode (when login is needed)
python pixiv_token_fetcher.py -u "your_email" -p "your_password" --no-headless
# Force a fresh browser login (ignore cache)
python pixiv_token_fetcher.py -u "your_email" -p "your_password" --force-login
# Custom cache directory
python pixiv_token_fetcher.py --cache-dir ./tokens
# Machine-readable: full record as JSON on stdout (status logs go to stderr)
python pixiv_token_fetcher.py --json
# Pipeline-friendly: print a single field only (no labels, no emoji)
ACCESS_TOKEN=$(python pixiv_token_fetcher.py --print access_token)
REFRESH=$(python pixiv_token_fetcher.py --print refresh_token)
# Verbosity (logs are written to stderr only)
python pixiv_token_fetcher.py --verbose # debug-level logs
python pixiv_token_fetcher.py --quiet # warnings/errors only
# If installed via `pip install .`, the same CLI is available as `pixiv-token`
pixiv-token --print access_token
Default cache directory: ~/.pixiv-token/, one file per account (<email>.json). Each file stores username, access_token, refresh_token, and expires_at — treat the directory like a credential store.
As a module
from pixiv_token_fetcher import PixivTokenFetcher
# First login for an account — credentials required
fetcher = PixivTokenFetcher(
username="your_pixiv_email",
password="your_pixiv_password",
headless=True,
)
token = fetcher.get_token() # cache → refresh → browser login (in that order)
print(token["access_token"])
# Later, reuse the cache without credentials
fetcher = PixivTokenFetcher(account="your_pixiv_email")
token = fetcher.get_token()
# List cached accounts
for acc in PixivTokenFetcher().list_cached_accounts():
print(acc["username"], acc["expires_at"])
The returned token dict always contains username, access_token, refresh_token, and expires_at (unix seconds).
Logging: the library uses the standard logging module under the logger name pixiv_token_fetcher and ships no handlers by default (silent on import). Wire it into your own setup:
import logging
logging.getLogger("pixiv_token_fetcher").setLevel(logging.INFO)
logging.basicConfig(format="%(asctime)s %(levelname)s %(message)s")
🔧 How It Works
- Cache Lookup — Resolves the account (explicit
--account/--username, or auto-detected if only one is cached) and reads~/.pixiv-token/<email>.json; ifaccess_tokenis still valid, returns it immediately - Refresh — If the access token has expired, calls Pixiv's
grant_type=refresh_tokenendpoint and updates the cache (no browser involved) - PKCE Generation (fallback) — Generates
code_verifierandcode_challengefor OAuth PKCE flow - Browser Launch — Launches a stealth Chromium build to perform the login
- Auto Login — Fills in email/password with slow typing to mimic human input
- Code Capture — Intercepts the
pixiv://account/login?code=...redirect via CDP (Network.requestWillBeSent) - Security Prompt Handling — Automatically clicks "Remind me later" / "Skip" if Pixiv shows a Passkeys/2FA setup page
- Token Exchange — Exchanges the authorization code for access & refresh tokens and writes them to the cache
📌 Notes
- ⚠️ Do not hardcode credentials in production environments. Use environment variables or a secrets manager.
- ❌ This is not an official Pixiv SDK. Changes to Pixiv's login page may affect functionality.
- 🛡 Please comply with Pixiv's Terms of Service.
- 🔁 The refresh token is long-lived. You typically only need to run this tool once.
🧪 Example Output
[INFO] opening pixiv login page
[INFO] filled username field
[INFO] filled password field
[INFO] submitted login form
[INFO] skipping security prompt via 'Remind me later' button
[INFO] captured authorization code
access_token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
refresh_token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
expires_at: 2026-05-25 14:32:10
The [INFO] lines are logs (written to stderr); access_token / refresh_token / expires_at are the result (written to stdout). Pipe-friendly.
🧪 Testing
Unit tests cover the non-browser logic (cache I/O, account resolution, token-refresh orchestration, CLI output contracts). Browser flow is mocked, so the suite runs in under a second without needing CloakBrowser/Playwright installed.
pip install -e ".[test]"
pytest
📝 License
See the LICENSE file for license rights and limitations (MIT).
🙋♀️ Contribution & Issues
Pull Requests and Issues are welcome!
📫 Contact
- GitHub: piglig
- Email: zhu1197437384@gmail.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pixiv_token-0.1.0.tar.gz.
File metadata
- Download URL: pixiv_token-0.1.0.tar.gz
- Upload date:
- Size: 11.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c41f602bc01b7f8a5954091bf17e455261a56ffafff2c06bc0e9897b482b602d
|
|
| MD5 |
7a63e0181dcfdc16ede3dc7bfe279ad7
|
|
| BLAKE2b-256 |
c38eb8ddd06a3abe748552f59231c35c086eb5af5d002f829075a5d7bb68ed46
|
Provenance
The following attestation bundles were made for pixiv_token-0.1.0.tar.gz:
Publisher:
publish.yml on piglig/pixiv-token
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pixiv_token-0.1.0.tar.gz -
Subject digest:
c41f602bc01b7f8a5954091bf17e455261a56ffafff2c06bc0e9897b482b602d - Sigstore transparency entry: 1629184933
- Sigstore integration time:
-
Permalink:
piglig/pixiv-token@d748129be3cd472eeb900e72a864f6861466333c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/piglig
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d748129be3cd472eeb900e72a864f6861466333c -
Trigger Event:
release
-
Statement type:
File details
Details for the file pixiv_token-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pixiv_token-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d049e76e3e82fba16d51b6bac28b0ec2bce9991a6d16a5aff30188f9d54e55c5
|
|
| MD5 |
9747dc5d4155337b62b4093527b06d86
|
|
| BLAKE2b-256 |
f18e7aaa3319f9b43b982d2af07c7a7ed8e54f45beb6595415dc7410418fddbc
|
Provenance
The following attestation bundles were made for pixiv_token-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on piglig/pixiv-token
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pixiv_token-0.1.0-py3-none-any.whl -
Subject digest:
d049e76e3e82fba16d51b6bac28b0ec2bce9991a6d16a5aff30188f9d54e55c5 - Sigstore transparency entry: 1629184950
- Sigstore integration time:
-
Permalink:
piglig/pixiv-token@d748129be3cd472eeb900e72a864f6861466333c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/piglig
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d748129be3cd472eeb900e72a864f6861466333c -
Trigger Event:
release
-
Statement type: