# How biliTickerBuy Generates cToken and Browser Fingerprints for Bilibili Ticket API

> Discover how biliTickerBuy generates cToken and browser fingerprints using Python modules to emulate Bilibili client behavior. Learn essential details for API interaction.

- Repository: [Qizhuo Xie/biliTickerBuy](https://github.com/mikumifa/biliTickerBuy)
- Tags: deep-dive
- Published: 2026-06-23

---

**biliTickerBuy generates cToken and browser fingerprints through two independent Python modules: a deterministic timing-based encoder in [`cptoken/__init__.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/cptoken/__init__.py) and a synthetic browser environment generator in [`util/request/BrowerState.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/util/request/BrowerState.py), both designed to emulate legitimate Bilibili client behavior.**

The open-source tool **biliTickerBuy** (mikumifa/biliTickerBuy) implements sophisticated anti-detection mechanisms to interact with Bilibili's ticket purchase API. By synthesizing cryptographically plausible cTokens and realistic browser fingerprints, the tool mimics genuine user sessions. This article examines the exact implementation details, source file locations, and function signatures that power these generation routines.

## Understanding cToken Generation in biliTickerBuy

The cToken is a base-64-encoded opaque token that encodes timing-related counters and browser state metrics. The generation logic resides entirely within [`cptoken/__init__.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/cptoken/__init__.py) and operates through a stateful runtime system.

### The Core generate_ctoken Function

At lines 14-78 of [`cptoken/__init__.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/cptoken/__init__.py), the **`generate_ctoken`** function constructs the binary payload. It accepts multiple integer fields—including `m1`, `touchend`, `m2` through `m9`, `timer`, and `timediff`—and converts each to specific byte representations:

- Single-byte fields use `_b1` conversion
- Larger counters use two-byte big-endian encoding
- The final byte array is passed through `base64.b64encode` to produce the opaque string

This deterministic encoding ensures that identical input states produce identical cTokens, while the variability introduced elsewhere ensures uniqueness across requests.

### Initializing Runtime State with CTokenRuntimeState

The **`CTokenRuntimeState`** class (lines 80-115) manages the raw counters and timestamps required for token generation. The **`init_ctoken_state`** function creates a fresh runtime using a **derived deterministic function** (`derive_d`) that mixes screen metrics, browser history length, user-agent length, and the current millisecond time (`now_mod_256`).

Key implementation details:
- Fields `m1` through `m9` populate derived values based on browser window state
- Fields like `openWindow` receive randomized small integers
- The function logs the initial snapshot for debugging before returning the runtime object

The derivation logic appears at lines 92-113, where mathematical operations on window dimensions and temporal data create the initial entropy.

### Simulating Request Snapshots

To mimic realistic user interaction patterns, the **`sim_ctoken_state`** function (lines 334-366) creates temporal snapshots that simulate the passage of time between requests. This function:
- Accepts a previous state and current millisecond timestamp
- Applies small random increments to `touchend`, `openWindow`, and `visibilitychange` counters
- Returns a `CTokenSnapshot` via the **`snapshot`** method (lines 150-176)

The snapshot method updates the `timer` based on elapsed seconds and incorporates any `timediff` accumulated since the ticket collection timestamp. This allows the buying workflow to generate fresh "prepare" tokens for each API request while maintaining temporal consistency.

**Typical implementation in the buy flow:**

```python
from cptoken import init_ctoken_state, sim_ctoken_state
import time

# Initialise a cToken runtime state (once per process)

runtime = init_ctoken_state(
    browser_window_state=generate_browser_window_state(),
    ticket_collection_t=int(time.time() * 1000)
)

# When preparing a request, obtain a fresh token snapshot

prepare_snapshot = sim_ctoken_state(runtime)
prepare_ctoken = prepare_snapshot.generate_prepare_ctoken()
payload["ctoken"] = prepare_ctoken

```

This pattern appears in [`task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/task/buy.py) at lines 470-482, where the generated token attaches to the prepare request payload.

## Browser Fingerprint Generation Implementation

All fingerprint synthesis occurs in [`util/request/BrowerState.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/util/request/BrowerState.py) (note the intentional misspelling in the filename). This module constructs a JSON-like structure mimicking real browser fields including window dimensions, navigator properties, WebGL contexts, and canvas hashes.

### Browser State Data Structures

Lines 14-99 define **TypedDicts** that enforce the exact schema expected by Bilibili's API:

- **`BrowserWindowState`**: Inner/outer dimensions, scroll offsets, screen positioning
- **`BrowserDisplayState`**: `devicePixelRatio`, `colorDepth`, `pixelDepth`
- **`BrowserNavigatorState`**: User-agent strings, platform, hardware concurrency
- **`BrowserWebGLState`** and **`BrowserCanvasState`**: Graphics rendering fingerprints

These type definitions ensure that generated fingerprints match the expected server-side validation patterns.

### Generating Individual Browser Components

The module provides discrete generators for each browser subsystem:

**`generate_browser_window_state`** (lines 167-268) selects realistic screen resolutions and calculates inner/outer window dimensions. It randomizes between maximized and windowed layouts while computing plausible scroll offsets.

**`generate_browser_display_state`** (lines 274-300) derives display metrics from the selected screen size, producing consistent `devicePixelRatio` values appropriate for the purported hardware.

**`generate_browser_navigator_state`** (lines 308-666) constructs Chrome-style user-agent strings, platform identifiers, language lists, and hardware concurrency counts that match the selected operating system profile.

Additional generators handle locale (`generate_browser_locale_state`), geolocation (`generate_browser_location_state`), WebGL vendor/renderer strings (`generate_browser_webgl_state`), and canvas hashing (`generate_browser_canvas_state`).

**`generate_browser_fingerprint_state`** (lines 622-705) orchestrates these helpers into a single **`BrowserFingerprintState`** dictionary. This function is deliberately pure-functional; the generated fingerprint should be cached and reused across multiple requests to maintain internal consistency (e.g., identical canvas hashes and WebGL fingerprints throughout a session).

### Building Request Headers from Browser State

The **`build_headers_from_browser_state`** function (lines 801-880) transforms the fingerprint dictionary into legitimate HTTP headers. It produces:

- `User-Agent` and `Accept-Language` headers
- `Sec-CH-UA` client hints
- Cookie strings and request metadata
- Referrer policies matching the synthetic browser state

**Integration example:**

```python
from util.request.BrowerState import generate_browser_fingerprint_state, build_headers_from_browser_state

# Generate a full fingerprint dict (once per session)

fingerprint = generate_browser_fingerprint_state(
    os_name="windows",
    locale="zh-CN"
)

# Build request headers from the fingerprint

headers = build_headers_from_browser_state(
    state=fingerprint,
    referer="https://show.bilibili.com/",
    base_headers={"X-Requested-With": "XMLHttpRequest"}
)

# Use these headers when issuing Bilibili API calls

response = requests.post(
    url="https://show.bilibili.com/api/ticket/prepare",
    json=payload,
    headers=headers
)

```

This pattern appears in [`util/request/BiliRequest.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/util/request/BiliRequest.py) (lines 13-31), where the generator initializes the state and constructs headers for HTTP requests.

## Summary

- **cToken generation** occurs in [`cptoken/__init__.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/cptoken/__init__.py) through deterministic encoding of timing counters and browser metrics, using `CTokenRuntimeState` for lifecycle management and `sim_ctoken_state` for temporal simulation.
- **Browser fingerprint synthesis** happens in [`util/request/BrowerState.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/util/request/BrowerState.py), where typed dictionaries enforce API-compliant structures across window, display, navigator, WebGL, and canvas attributes.
- **Integration** requires caching the browser fingerprint for session consistency while generating fresh cToken snapshots for each API request, as demonstrated in [`task/buy.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/task/buy.py).
- Both systems employ pure Python implementations with deterministic seeds to ensure reproducibility while introducing sufficient variability to avoid detection patterns.

## Frequently Asked Questions

### What is the purpose of the cToken in biliTickerBuy?

The cToken serves as an opaque authentication credential required by Bilibili's ticket API. According to the source code in [`cptoken/__init__.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/cptoken/__init__.py), it encodes temporal state (timestamps, delays) and browser interaction metrics (window states, touch events) into a base-64 string that validates the client as a legitimate browser session rather than an automated script.

### Why does the browser fingerprint generator use TypedDicts?

The TypedDicts defined in [`util/request/BrowerState.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/util/request/BrowerState.py) (lines 14-99) enforce compile-time type safety for the complex nested structures expected by Bilibili's anti-bot systems. By strictly typing fields like `devicePixelRatio`, `hardwareConcurrency`, and WebGL vendor strings, the code ensures that generated fingerprints match the exact schema that server-side validation logic expects, reducing the risk of request rejection due to malformed JSON.

### How does sim_ctoken_state prevent detection during rapid requests?

The `sim_ctoken_state` function in [`cptoken/__init__.py`](https://github.com/mikumifa/biliTickerBuy/blob/main/cptoken/__init__.py) (lines 334-366) introduces micro-variations in timing fields between sequential requests. By incrementing `touchend`, `openWindow`, and `visibilitychange` counters with small random values and updating the `timer` based on actual elapsed milliseconds, it simulates the natural irregularity of human browsing patterns. This prevents the identical cToken repetition that automated detection systems often flag as bot behavior.

### Can the browser fingerprint be reused across multiple ticket purchase attempts?

Yes, and the source code explicitly recommends this approach. The `generate_browser_fingerprint_state` function (lines 622-705) is designed to be pure-functional, meaning it should be called once per session and cached. Reusing the same fingerprint ensures consistency in critical identifying fields like canvas hashes, WebGL vendor/renderer strings, and user-agent across all requests in a purchase flow, whereas regenerating these values mid-session would trigger consistency checks on Bilibili's servers.