Skip to content

Repository files navigation

EasyBili

简体中文

EasyBili is a typed Swift client for Bilibili's web APIs. The package focuses on a small, dependable core: async/await, explicit errors, resilient Codable models, injectable networking, and source compatibility with the original callback API.

Important

Bilibili's web APIs are unofficial and can change without notice. EasyBili is not affiliated with or endorsed by Bilibili. Use it for learning and personal projects, respect the platform's terms, and avoid aggressive request rates.

Requirements

  • Swift 5.7+
  • iOS 14+, macOS 11+, or tvOS 14+

Installation

Add https://github.com/RyouDYFZ/EasyBili in Xcode's File > Add Packages, or add it to Package.swift:

.package(url: "https://github.com/RyouDYFZ/EasyBili", branch: "main")

Usage

import EasyBili

let client = BilibiliClient()

do {
    let page = try await client.popularVideos(page: 1, pageSize: 20)
    for video in page.videos {
        print(video.title, video.owner.name, video.stat.views)
    }

    let detail = try await client.video(bvid: "BV1xx411c7mD")
    let results = try await client.searchVideos(query: "Swift")
    let creator = try await client.userCard(userID: detail.owner.id)
    print(results.totalResults, creator.profile.name)
} catch {
    print("Bilibili request failed:", error.localizedDescription)
}

Typed APIs now cover videos/search/users, history, watch later, favorites, comments and replies, dynamic feeds, followed bangumi, playback metadata, subtitle tracks/documents, and segmented danmaku data. See the API support matrix for endpoint and authentication details.

Lazy pagination is available for cursor and page-number APIs:

for try await page in client.historyPages(pageSize: 20) {
    for item in page { print(item.title) }
}

Configuration and authentication state

Headers can be configured without coupling the package to a credential store:

let credentials = BilibiliCredentials(
    sessdata: "...",
    csrfToken: "...",
    userID: "...",
    buvid3: "..."
)
let configuration = BilibiliConfiguration(credentials: credentials)
let client = BilibiliClient(configuration: configuration)

Never commit cookies or tokens. Credentials remain in memory and are not persisted by EasyBili. WBI signing is automatic for typed WBI endpoints: keys are loaded from navigation state, cached for six hours, and can be refreshed with await client.invalidateWBIKeys(). EasyBili does not generate or activate device identifiers.

Writes are disabled by default. Likes, follows, favorite/watch-later changes, and comments require an explicit opt-in plus SESSDATA and bili_jct:

var configuration = BilibiliConfiguration(credentials: credentials)
configuration.allowsWriteOperations = true
let client = BilibiliClient(configuration: configuration)
try await client.setVideoLike(aid: 42, isLiked: true)

Playback and danmaku

EasyBili returns DASH/direct playback metadata, player information, subtitle tracks, subtitle documents, and raw protobuf danmaku. Import the optional EasyBiliDanmaku product to decode segments without adding a third-party protobuf runtime:

import EasyBiliDanmaku

let segment = try await client.danmakuSegment(aid: 42, cid: 99, segmentIndex: 1)
print(segment.elements.first?.content ?? "")

Reliability controls

Endpoint policies declare signing, authentication, rate-limit group, idempotency, and write behavior. URLSession cancellation propagates from Swift tasks; idempotent requests retry transient transport/429/5xx failures with bounded backoff. minimumRequestInterval enables per-group pacing, and the optional event handler reports redacted lifecycle metadata only.

Add an endpoint locally

The public typed request mechanism makes uncovered REST endpoints usable immediately:

struct ServerClock: Decodable {
    let now: Int
}

let request = BiliRequest<ServerClock>(path: "/x/report/click/now")
let clock = try await client.send(request)

For a custom endpoint that requires WBI, pass signing: .wbi to BiliRequest.

Legacy callbacks

EasyBili.shared.fetchPopularVideos and fetchRecommendedVideos remain available for source compatibility, but are deprecated because they cannot return meaningful errors.

Development

swift test --parallel
Scripts/check-coverage.sh 50
Scripts/check-api-compatibility.sh

The tests use injected fixture transports and do not call Bilibili. A runnable sample is available with swift run EasyBiliExample; set BILIBILI_SESSDATA only if you also want its history example. See CONTRIBUTING.md, CHANGELOG.md, and SECURITY.md.

If macOS reports resource fork ... not allowed while the repository is inside a File Provider-synced folder, build outside that folder with swift test --scratch-path /tmp/easybili-build.

License

EasyBili is available under the MIT License.

About

A lightweight library written in Swift to fetch trending & recommendation videos in BiliBili

Resources

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages