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.
- Swift 5.7+
- iOS 14+, macOS 11+, or tvOS 14+
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")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) }
}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)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 ?? "")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.
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.
EasyBili.shared.fetchPopularVideos and fetchRecommendedVideos remain available for source compatibility, but are deprecated because they cannot return meaningful errors.
swift test --parallel
Scripts/check-coverage.sh 50
Scripts/check-api-compatibility.shThe 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.
EasyBili is available under the MIT License.