Skip to main content

Async Python client for Sakamichi Group Message API (Nogizaka46, Sakurazaka46, Hinatazaka46)

Project description

pysaka

PyPI version License: MIT

Build Status

Disclaimer & Warnings

[!CAUTION] Use at your own risk. accessing the API via unauthorized means may violate the Terms of Service of the respective platforms. This library is for educational purposes only.

規約 / Terms of Service Ref.

Users must agree to the official Terms of Service of the respective platforms. The following are excerpts from the official terms (as of writing):

第3条(知的財産権)/ Article 3 (Intellectual Property)

  1. 当社が別に定める場合を除き、お客様が本コンテンツを複製、翻案、頒布、公衆送信等することは禁止します。

第8条(禁止事項)/ Article 8 (Prohibited Acts)

(11) 当社または第三者の情報、データおよびソフトウェアを修正、改変、改ざん、リバースエンジニアリング、逆コンパイル、逆アッセンブルまたは消去等する行為

(16) 当社が指定するアクセス方法以外の手段で本サービスにアクセスし、またはアクセスを試みる行為

(17) 自動化された手段(クローラおよび類似の技術を含む)を用いて本サービスにアクセスし、またはアクセスを試みる行為

Async Python client for Sakamichi Groups (Nogizaka46, Sakurazaka46, Hinatazaka46, Yodel) Message API.

pysaka provides a robust, type-hinted, and async interface to interact with the official Message apps for all supported groups. It handles authentication (via browser), token management, and data retrieval.

Features

  • 🔐 Browser Authentication: Seamless interactive login via Playwright (compatible with MFA/SSO).
  • 🍪 Auto-Refresh: Automatically refreshes access tokens using captured cookies.
  • 🚀 Async/Await: Built on aiohttp for high-performance concurrent requests.
  • 📦 Multi-Group: Supports Nogizaka46, Sakurazaka46, Hinatazaka46, and Yodel out of the box.
  • 📝 Blog Scraper: Backup official blogs (HTML + images) for all three groups.
  • 🛠️ Type Hinted: 100% type coverage for better IDE support.

Configuration

pysaka uses structlog for observability. You can control the logging output via environment variables:

  • HAKO_ENV=development (default): Pretty-printed, colored console logs.
  • HAKO_ENV=production: Structured JSON logs with automatic secret redaction.

Installation

Recommended install via uv:

uv add pysaka

For development:

git clone https://github.com/xebjhm/pysaka.git
cd pysaka
uv sync

Quick Start

1. Authentication

Use BrowserAuth to log in interactively. This launches a browser window for you to enter credentials.

import asyncio
from pysaka import BrowserAuth, Group

async def login():
    creds = await BrowserAuth.login(Group.NOGIZAKA46)
    print(creds['access_token'])

asyncio.run(login())

2. Fetching Data

Initialize the Client with your credentials.

import asyncio
import aiohttp
from pysaka import Client, Group

async def main():
    # ... assume creds obtained via BrowserAuth ...
    token = "YOUR_ACCESS_TOKEN" 
    
    async with aiohttp.ClientSession() as session:
        client = Client(Group.NOGIZAKA46, access_token=token)
        
        # Get Profile
        profile = await client.get_profile(session)
        print(f"Hello, {profile['nickname']}!")
        
        # Get Groups (Members)
        groups = await client.get_groups(session)
        for g in groups:
            print(f"{g['name']} (ID: {g['id']})")

asyncio.run(main())

3. Blog Scraping (No Auth Required)

Scrape official blogs for any group without authentication.

import asyncio
import aiohttp
from pysaka.blog import NogizakaBlogScraper, HinatazakaBlogScraper, SakurazakaBlogScraper

async def scrape_blogs():
    async with aiohttp.ClientSession() as session:
        scraper = NogizakaBlogScraper(session)

        # Get all active members
        members = await scraper.get_members()
        print(f"Found {len(members)} members")

        # Get blogs for a specific member
        async for blog in scraper.get_blogs(member_id="some_member_code"):
            print(f"{blog.title} - {blog.published_at}")

asyncio.run(scrape_blogs())

API Reference

Client

The main entry point.

  • __init__(group, access_token, ...): Initialize client.
  • get_profile(session): Get current user profile.
  • get_groups(session): List subscribed members/groups.
  • get_messages(session, group_id, ...): Fetch messages timeline.
  • get_news(session): Fetch official announcements.
  • get_tags(session): Fetch tags.
  • get_fc_contents(session): Fetch Fan Club content.
  • get_organizations(session): Fetch organizations.
  • get_products(session, product_type): Fetch products (subscriptions).
  • post_json(session, endpoint, data): Perform JSON POST requests.
  • delete_json(session, endpoint): Perform DELETE requests.
  • download_file(session, url, filepath): Download a file to local filesystem.
  • get_member(session, member_id): Fetch individual member details.
  • get_account(session): Fetch user account information.
  • get_letters(session, group_id): Fetch user's sent letters/cards.
  • get_past_messages(session, group_id): Fetch historical messages.
  • get_subscription_streak(session, group_id): Fetch consecutive subscription days.
  • add_favorite(session, message_id): Add a message to favorites.
  • remove_favorite(session, message_id): Remove a message from favorites.
  • refresh_if_needed(session): Lazy token refresh if expiring soon.

Credential Management

  • get_token_manager(): Get the singleton TokenManager instance for secure credential storage.
  • TokenManager.save_session(group, access_token, ...): Save session credentials to system keyring.
  • TokenManager.load_session(group): Load stored session credentials.
  • TokenManager.delete_session(group): Remove stored credentials.

BrowserAuth

Helper for OAuth2 flow.

  • login(group, headless=False, ...): Perform login and capture tokens.

Blog Scrapers

Public blog scrapers (no authentication required).

  • NogizakaBlogScraper(session): Nogizaka46 official blog.
  • SakurazakaBlogScraper(session): Sakurazaka46 official blog.
  • HinatazakaBlogScraper(session): Hinatazaka46 official blog.

Each scraper provides:

  • get_members(): Get dict of member_id -> member_name.
  • get_blogs(member_id, since_date=None): AsyncIterator of BlogEntry objects.
  • get_blog_detail(blog_id, member_id=None): Fetch single blog by ID.

Exceptions

  • SakaError: Base exception for all pysaka errors.
  • AuthError: Authentication related errors.
  • ApiError: API request errors (includes status_code attribute).
  • SessionExpiredError: Session invalidated server-side (e.g., logged in from another device).
  • RefreshFailedError: All token refresh attempts failed unexpectedly.
  • BlogGoneError: Blog post has been permanently removed (HTTP 404/410).

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysaka-0.3.0.tar.gz (267.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pysaka-0.3.0-py3-none-any.whl (49.6 kB view details)

Uploaded Python 3

File details

Details for the file pysaka-0.3.0.tar.gz.

File metadata

  • Download URL: pysaka-0.3.0.tar.gz
  • Upload date:
  • Size: 267.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pysaka-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f8fd6925db8890b6138568dfd4363746403376f0543b0606e109f08a691e642a
MD5 3aee7845c6128a5f813828306936e999
BLAKE2b-256 c864beb190875df3c6243c7fcbe81378a508bde448d84efa9c6b85543397ba6a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysaka-0.3.0.tar.gz:

Publisher: publish.yml on xebjhm/pysaka

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pysaka-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pysaka-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 49.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pysaka-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b06e20cbad28e59099e65ce03770c5da68530e750eedf448f9f150b73fb7f0af
MD5 e14968beb450533f71179136142284e6
BLAKE2b-256 187b455890d4aee5436e74b0b53cc736bdb315bfffee6bccb2be10c2423961e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysaka-0.3.0-py3-none-any.whl:

Publisher: publish.yml on xebjhm/pysaka

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page