Answers
What is a b23.tv link, and how do I get the Bilibili video ID from it?
Short answer
b23.tv is Bilibili's short-link domain: each link answers with an HTTP redirect to the full bilibili.com page, and for a video the BV id is in that target URL. Read the redirect yourself for free, or pass the link as url to okdata Bilibili video detail, which resolves it and returns the BV id with the video's stats for $0.002.
When someone taps share in the Bilibili app, the text they copy ends in a b23.tv link, something like 【开箱】这台键盘有点东西 https://b23.tv/k9Xq2Rm. b23.tv is Bilibili's own short-link domain. The link holds no data itself; it answers with an HTTP 302 redirect to the full bilibili.com address, and for a video that address contains the BV id.
The forms you will meet
| Short link | Redirects to | ID visible without resolving? |
|---|---|---|
https://b23.tv/BV1... |
https://www.bilibili.com/video/BV1... |
Yes, the path is the BV id |
https://b23.tv/av170001 |
https://www.bilibili.com/video/av170001 |
The aid; convert it to a BV id |
https://b23.tv/ + a short code from the share button |
The full page, often with share tracking parameters after ? |
No, follow the redirect |
We checked the first two forms with a plain curl -I on 12 November 2026: both answered 302 with the www.bilibili.com/video/ target. Short codes are not limited to videos: most things in the app with a share button, a live room or an article for instance, get one too. Look at the target before you assume a BV id.
Two ways to get the ID
Resolve it yourself. One request that does not follow redirects, then read the Location header and match BV[0-9A-Za-z]{10}. It costs nothing and works for a few links. Run it from a server that Bilibili does not block, and do it at a modest pace.
Let the API resolve it. Bilibili video detail takes the short link as url, follows it, and returns the video: id is the BV id, and with view=full you also get ext.aid and ext.cid alongside views, likes, coins and danmaku count. Useful when you need the stats anyway, or when you would rather not run redirect code.
| Job | Calls | Cost |
|---|---|---|
| One shared link to BV id and stats | 1 | $0.002 |
| A sheet of 500 links from a campaign | 500 | $1.00 |
| BV id only, resolved yourself | 0 | free |
Example
import os, re, requests
API = "https://api.okdata.online/v1/bilibili/videos/get"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
BV = re.compile(r"BV[0-9A-Za-z]{10}")
def link_from_share_text(text: str) -> str:
m = re.search(r"https?://b23\.tv/[0-9A-Za-z]+", text)
if not m:
raise ValueError("no b23.tv link in the text")
return m.group(0)
def bvid_free(short: str) -> str | None:
r = requests.head(short, allow_redirects=False, timeout=15)
m = BV.search(r.headers.get("Location", ""))
return m.group(0) if m else None
def video_via_api(short: str) -> dict:
body = requests.get(API, headers=H, timeout=60, params={
"url": short, "view": "full",
"fields": "id,title,metrics.views,ext.aid"}).json()
if body["code"] != "ok":
raise RuntimeError(f'{body["code"]}: {body["message"]}')
return body["data"]["item"]
link = link_from_share_text("【开箱】这台键盘有点东西 https://b23.tv/k9Xq2Rm")
print(bvid_free(link) or video_via_api(link)["id"])
Limits
- Pass the link, not the whole share text:
urlmust be a single http(s) address. - If a short link leads to a live room, a profile or an article, video detail cannot read it. That call fails and is not charged.
- A link to a deleted or private video returns
not_found, which is free. - Short links can carry tracking parameters tied to the person who shared them. Strip everything after
?before you store or publish a link.
Douyin and Xiaohongshu have the same pattern with their own short domains; see converting a Douyin share link.
Sources
Where people asked this (read 2026-11-12)
Updated