Skip to main content

Unofficial Python SDK for Chzzk (NAVER Live Streaming Platform) API

Project description

chzzk-python

Python 3.12+ License: MIT Docker

Unofficial Python SDK for Chzzk (NAVER Live Streaming Platform) API

한국어

Installation

# Using uv (recommended)
uv add chzzk-python

# Using pip
pip install chzzk-python

CLI Installation

# Using uv (recommended)
uv add "chzzk-python[cli]"

# Using pip
pip install "chzzk-python[cli]"

Docker

# Pull from GitHub Container Registry
docker pull ghcr.io/hypn4/chzzk-python:latest

# Run CLI commands
docker run --rm ghcr.io/hypn4/chzzk-python --help
docker run --rm ghcr.io/hypn4/chzzk-python auth --help

# Watch chat (with environment variables)
docker run --rm -it \
  -e CHZZK_NID_AUT="your-nid-aut" \
  -e CHZZK_NID_SES="your-nid-ses" \
  ghcr.io/hypn4/chzzk-python chat watch CHANNEL_ID

# Interactive chat (requires -it flags)
docker run --rm -it \
  -e CHZZK_NID_AUT="your-nid-aut" \
  -e CHZZK_NID_SES="your-nid-ses" \
  ghcr.io/hypn4/chzzk-python chat send CHANNEL_ID -i

Available tags: latest, X.Y.Z, X.Y, X

Docker Compose

# Copy and configure environment variables
cp .env.example .env
# Edit .env with your credentials and channel ID

# Run CLI commands
docker compose run --rm chzzk --help
docker compose run --rm chzzk live info CHANNEL_ID

# Watch chat (background service with auto-restart)
docker compose --profile chat up -d chat-watch

# Interactive chat mode
docker compose --profile interactive run --rm chat-interactive

# View logs
docker compose --profile chat logs -f chat-watch

# Stop services
docker compose --profile chat down

Quick Start

from chzzk import ChzzkClient, FileTokenStorage

# Create client with OAuth support
client = ChzzkClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    redirect_uri="http://localhost:8080/callback",
    token_storage=FileTokenStorage("token.json"),
)

# Generate authorization URL
auth_url, state = client.get_authorization_url()
# User visits auth_url and authorizes the app

# Exchange code for token (after OAuth callback)
token = client.authenticate(code="auth-code", state=state)

# Use the API
user = client.user.get_me()
print(f"Channel: {user.channel_name}")

API Categories & Implementation Status

Category Status Description
Authorization ✅ Implemented OAuth 2.0, Token issue/refresh/revoke
User ✅ Implemented Get logged-in user info
Channel ✅ Implemented Channel info, managers, followers, subscribers
Category ✅ Implemented Category search
Live ✅ Implemented Live list, stream key, broadcast settings
Chat ✅ Implemented Send messages, announcements, chat settings
Session ✅ Implemented Session create/list, event subscription
Restriction ✅ Implemented Activity restriction list management
Drops ❌ Not Implemented -
Webhook Event ❌ Not Implemented -

A CLI is also available for quick terminal access.

Features

Sync/Async Support

Both synchronous and asynchronous clients are available:

# Synchronous
from chzzk import ChzzkClient

with ChzzkClient(client_id="...", client_secret="...") as client:
    user = client.user.get_me()

# Asynchronous
from chzzk import AsyncChzzkClient

async with AsyncChzzkClient(client_id="...", client_secret="...") as client:
    user = await client.user.get_me()

Token Storage

Multiple token storage options:

from chzzk import InMemoryTokenStorage, FileTokenStorage, CallbackTokenStorage

# In-memory (default)
storage = InMemoryTokenStorage()

# File-based persistence
storage = FileTokenStorage("token.json")

# Custom callback
storage = CallbackTokenStorage(
    get_callback=lambda: load_from_db(),
    save_callback=lambda token: save_to_db(token),
    delete_callback=lambda: delete_from_db(),
)

Realtime Events

Receive chat, donation, and subscription events in realtime:

from chzzk import ChzzkClient, ChatEvent, DonationEvent, SubscriptionEvent

client = ChzzkClient(...)
event_client = client.create_event_client()

@event_client.on_chat
def on_chat(event: ChatEvent):
    print(f"{event.profile.nickname}: {event.content}")

@event_client.on_donation
def on_donation(event: DonationEvent):
    print(f"{event.donator_nickname} donated {event.pay_amount}won")

@event_client.on_subscription
def on_subscription(event: SubscriptionEvent):
    print(f"{event.subscriber_nickname} subscribed!")

# Connect and subscribe
event_client.connect()
event_client.subscribe_chat()
event_client.subscribe_donation()
event_client.subscribe_subscription()
event_client.run_forever()

Usage Examples

OAuth Authentication Flow

from chzzk import ChzzkClient, FileTokenStorage

client = ChzzkClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    redirect_uri="http://localhost:8080/callback",
    token_storage=FileTokenStorage("token.json"),
    auto_refresh=True,  # Automatically refresh expired tokens
)

# 1. Generate authorization URL
auth_url, state = client.get_authorization_url()
print(f"Visit: {auth_url}")

# 2. After user authorizes, exchange code for token
token = client.authenticate(code="received-code", state=state)

# 3. Refresh token manually if needed
new_token = client.refresh_token()

# 4. Revoke token on logout
client.revoke_token()

Channel & Live Information

# Get channel info
channel = client.channel.get_channel("channel-id")
print(f"Channel: {channel.channel_name}")
print(f"Description: {channel.channel_description}")

# Get followers
followers = client.channel.get_followers(size=20)
for follower in followers.data:
    print(f"Follower: {follower.nickname}")

# Get live broadcasts
lives = client.live.get_lives(size=10)
for live in lives.data:
    print(f"{live.channel_name}: {live.live_title} ({live.concurrent_user_count} viewers)")

# Get/Update live settings
setting = client.live.get_setting()
client.live.update_setting(default_live_title="My Stream Title")

Chat Messages

# Send chat message
client.chat.send_message(channel_id="channel-id", message="Hello!")

# Set chat announcement
client.chat.set_notice(
    channel_id="channel-id",
    message="Welcome to the stream!",
)

# Get/Update chat settings
settings = client.chat.get_settings(channel_id="channel-id")
client.chat.update_settings(
    channel_id="channel-id",
    chat_available_group="FOLLOWER",
)

Async Example

import asyncio
from chzzk import AsyncChzzkClient, FileTokenStorage

async def main():
    async with AsyncChzzkClient(
        client_id="your-client-id",
        client_secret="your-client-secret",
        redirect_uri="http://localhost:8080/callback",
        token_storage=FileTokenStorage("token.json"),
    ) as client:
        # Get user info
        user = await client.user.get_me()
        print(f"Channel: {user.channel_name}")

        # Get live broadcasts
        lives = await client.live.get_lives(size=10)
        for live in lives.data:
            print(f"{live.channel_name}: {live.live_title}")

asyncio.run(main())

Exception Handling

from chzzk import (
    ChzzkError,              # Base exception
    ChzzkAPIError,           # API error response
    AuthenticationError,     # 401 errors
    InvalidTokenError,       # Invalid/expired token
    InvalidClientError,      # Invalid client credentials
    ForbiddenError,          # 403 errors
    NotFoundError,           # 404 errors
    RateLimitError,          # 429 errors
    ServerError,             # 5xx errors
    TokenExpiredError,       # Token expired, need re-auth
    InvalidStateError,       # OAuth state mismatch
    SessionError,            # Session-related errors
    SessionConnectionError,  # Socket.IO connection failed
    SessionLimitExceededError,  # Max session limit exceeded
    EventSubscriptionError,  # Event subscription failed
)

try:
    user = client.user.get_me()
except InvalidTokenError:
    # Token is invalid or expired
    token = client.refresh_token()
except RateLimitError:
    # Rate limit exceeded, wait and retry
    time.sleep(60)
except ChzzkAPIError as e:
    print(f"API Error: [{e.status_code}] {e.error_code}: {e.message}")

Unofficial API

In addition to the official API, we provide an unofficial API using Naver cookie authentication. This enables real-time chat receiving/sending functionality.

⚠️ The unofficial API may change at any time and is not officially supported.

Unofficial Chat Client

Synchronous version:

from chzzk.unofficial import UnofficialChatClient, ChatMessage

chat = UnofficialChatClient(
    nid_aut="your-nid-aut-cookie",
    nid_ses="your-nid-ses-cookie",
)

@chat.on_chat
def on_chat(msg: ChatMessage):
    print(f"{msg.nickname}: {msg.content}")

@chat.on_donation
def on_donation(msg):
    print(f"{msg.nickname} donated {msg.pay_amount}won")

chat.connect("channel-id")
chat.send_message("Hello!")
chat.run_forever()

Asynchronous version:

from chzzk.unofficial import AsyncUnofficialChatClient, ChatMessage

async with AsyncUnofficialChatClient(
    nid_aut="your-nid-aut-cookie",
    nid_ses="your-nid-ses-cookie",
) as chat:
    @chat.on_chat
    async def on_chat(msg: ChatMessage):
        print(f"{msg.nickname}: {msg.content}")

    await chat.connect("channel-id")
    await chat.send_message("Hello!")
    await chat.run_forever()

Auto-Reconnection & Monitoring Options

The unofficial chat client automatically reconnects when the stream restarts or the chat channel changes. You can customize this behavior:

from chzzk.unofficial import AsyncUnofficialChatClient

chat = AsyncUnofficialChatClient(
    nid_aut="...",
    nid_ses="...",
    # Auto-reconnect settings
    auto_reconnect=True,              # Enable auto-reconnection (default: True)
    poll_interval=10.0,               # Status polling interval in seconds (default: 10)
    max_reconnect_attempts=5,         # Max reconnection attempts (default: 5)
    reconnect_backoff_base=1.0,       # Backoff base delay in seconds (default: 1)
    reconnect_backoff_max=30.0,       # Max backoff delay in seconds (default: 30)
    reconnect_wait_timeout=None,      # Reconnection wait timeout (None = infinite)
)

# Event handlers for connection status
@chat.on_live
async def on_live(event):
    print(f"Stream started: {event.live_title}")

@chat.on_offline
async def on_offline(event):
    print("Stream ended, waiting for restart...")

@chat.on_reconnect
async def on_reconnect(event):
    print(f"Reconnected! (attempt {event.attempt})")

@chat.on_reconnect_error
async def on_reconnect_error(error):
    print(f"Reconnection failed: {error}")

For long-running monitoring applications, you can configure infinite retry behavior:

from chzzk.unofficial.chat.monitor import MonitorConfig

# Create a custom monitor config
config = MonitorConfig(
    poll_interval_seconds=10.0,       # Poll every 10 seconds
    max_consecutive_failures=10,      # Trigger error callback after 10 failures
    infinite_retry=True,              # Continue monitoring even after failures
)

How to Get Naver Cookies

  1. Log in to Naver
  2. Browser Developer Tools (F12) → Application → Cookies
  3. Copy NID_AUT and NID_SES cookie values

Unofficial API Exception Handling

from chzzk import ChatConnectionError, ChatNotLiveError

try:
    chat.connect("channel-id")
except ChatNotLiveError:
    print("Channel is not currently live")
except ChatConnectionError as e:
    print(f"Connection failed: {e}")

Command Line Interface

A CLI is available for quick access to the unofficial API features.

Authentication

# Login via Naver QR code (recommended)
chzzk auth qr

# Login via Naver QR code with custom timeout
chzzk auth qr --timeout 60

# Save your Naver cookies manually (interactive)
chzzk auth login

# Check authentication status
chzzk auth status

# Remove stored cookies
chzzk auth logout

Cookies are stored in ~/.chzzk/cookies.json.

Live Status

# Get detailed live information
chzzk live info CHANNEL_ID

# Get simple LIVE/OFFLINE status
chzzk live status CHANNEL_ID

# JSON output
chzzk --json live info CHANNEL_ID

Chat

# Watch real-time chat
chzzk chat watch CHANNEL_ID

# Watch chat even when offline
chzzk chat watch CHANNEL_ID --offline

# Save chat to file
chzzk chat watch CHANNEL_ID --output chat.jsonl
chzzk chat watch CHANNEL_ID --output chat.txt --output-format txt

# Auto-generate filename based on stream info (recommended)
# Creates: {channel_id}_{live_id}_{YYYYMMDD}.jsonl
chzzk chat watch CHANNEL_ID --output-dir ./logs

# Disable auto-reconnection
chzzk chat watch CHANNEL_ID --no-auto-reconnect

# Custom poll interval (seconds)
chzzk chat watch CHANNEL_ID --poll-interval 5

# Send a single message (requires authentication)
chzzk chat send CHANNEL_ID "Hello!"

# Send to offline channel
chzzk chat send CHANNEL_ID "Hello!" --offline

# Interactive mode: send and receive messages
chzzk chat send CHANNEL_ID --interactive
# or
chzzk chat send CHANNEL_ID -i

# Interactive mode with chat logging
chzzk chat send CHANNEL_ID -i --output-dir ./logs

# Interactive mode with offline channel
chzzk chat send CHANNEL_ID -i --offline

Global Options

--nid-aut TEXT      # Override NID_AUT cookie (env: CHZZK_NID_AUT)
--nid-ses TEXT      # Override NID_SES cookie (env: CHZZK_NID_SES)
--json              # Output in JSON format
--log-level LEVEL   # Set log level (DEBUG, INFO, WARNING, ERROR)

Environment Variables

Variable Description
CHZZK_NID_AUT NID_AUT cookie value
CHZZK_NID_SES NID_SES cookie value
CHZZK_LOG_LEVEL Default log level
CHZZK_CHAT_OUTPUT Default chat output file path
CHZZK_CHAT_OUTPUT_DIR Default chat output directory (auto-generates filename)
CHZZK_CHAT_OUTPUT_FORMAT Default chat output format (jsonl, txt)
CHZZK_POLL_INTERVAL Live status polling interval in seconds (default: 10)
CHZZK_AUTO_RECONNECT Enable auto-reconnection (default: true, set "false" to disable)
CHZZK_TIMEZONE Timezone for chat timestamps and log filenames (default: Asia/Seoul)
TZ System timezone for Docker containers (default: Asia/Seoul)

Examples

See the examples directory for complete working examples:

  • oauth_server.py - OAuth authentication with Flask
  • realtime_chat.py - Realtime chat/donation/subscription events (sync)
  • realtime_chat_async.py - Realtime events (async)
  • session_management.py - Session management example
  • unofficial_chat.py - Unofficial chat client (sync)
  • unofficial_chat_async.py - Unofficial chat client (async)

API Reference

For detailed API documentation, see the Official Chzzk API Documentation.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Disclaimer

This is an unofficial SDK and is not affiliated with NAVER or Chzzk. Use at your own risk.

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

chzzk_python-0.14.1.tar.gz (178.4 kB view details)

Uploaded Source

Built Distribution

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

chzzk_python-0.14.1-py3-none-any.whl (93.7 kB view details)

Uploaded Python 3

File details

Details for the file chzzk_python-0.14.1.tar.gz.

File metadata

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

File hashes

Hashes for chzzk_python-0.14.1.tar.gz
Algorithm Hash digest
SHA256 9fcaf51a162b8bfc29ae63307e4935d5aef64997f8e6be8002486872d2efc98e
MD5 d4fcdbaa276c69deec8cc499c90fd18f
BLAKE2b-256 e6218372802a50ffc0edd2bc5e3217f0f5d6f344e90b448049ee2170a7762a58

See more details on using hashes here.

Provenance

The following attestation bundles were made for chzzk_python-0.14.1.tar.gz:

Publisher: publish.yml on hypn4/chzzk-python

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

File details

Details for the file chzzk_python-0.14.1-py3-none-any.whl.

File metadata

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

File hashes

Hashes for chzzk_python-0.14.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e44a87b6ba164518c4b5fd7372aa21804dc0d9b7974438148876d50d2feb6bc2
MD5 a65be7e196107dbda8569f70afbd23a0
BLAKE2b-256 aff83bd5e9c2eb4567573d318da23953fd398d36538cd116bb26de0dbb44d3c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for chzzk_python-0.14.1-py3-none-any.whl:

Publisher: publish.yml on hypn4/chzzk-python

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