Skip to content
Back to skills

Bilibili

ASecurity

Read and publish 专栏 articles on Bilibili (bilibili.com) with the user's own login cookies (BYOC) — list their published articles with view/like/comment stats, inspect one article, and publish a new article. Use when the user mentions Bilibili / B站 / 专栏, "我的B站专栏", reading article stats (阅读/点赞), or publishing/投稿 a 专栏 article.

  • 17 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
ai-agentspythongoshellbashapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 17, 2026

npx -y skills add AceDataCloud/Skills --skill bilibili --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bilibili?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Bilibili
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/acedatacloud-bilibili/badge)](https://www.skillsdirectory.com/skills/acedatacloud-bilibili)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: bilibili
description: Read and publish 专栏 articles on Bilibili (bilibili.com) with the user's own login cookies (BYOC) — list their published articles with view/like/comment stats, inspect one article, and publish a new article. Use when the user mentions Bilibili / B站 / 专栏, "我的B站专栏", reading article stats (阅读/点赞), or publishing/投稿 a 专栏 article.
when_to_use: |
  Trigger for anything on the user's Bilibili (bilibili.com) 专栏 account driven
  by their own login cookie: show who they are, list their published 专栏
  articles with view / like / comment counts, look at one article's stats, or
  publish a new 专栏 article. This acts as the user's real account, so writes are
  gated behind an explicit confirmation.
connections: [bilibili]
allowed_tools: [Bash]
license: Apache-2.0
metadata:
  author: acedatacloud
  version: "1.0"
---

# bilibili — read & publish 专栏 via your own cookies

Drives the user's **real** Bilibili 专栏 (article) account through the same
`api.bilibili.com` web endpoints the site uses, authenticated by the login
cookie they captured with the ACE extension. No browser, no third-party deps —
`urllib` + `hashlib` (the article-list read endpoint needs WBI signing, done
with stdlib).

The connector injects the cookie jar as an env var:

- `BILIBILI_COOKIES` — a JSON array of cookies. **Secret — never echo or print
  it.** It includes `SESSDATA` (auth) and `bili_jct` (the CSRF token used for
  writes).

## CLI

The skill ships [`scripts/bilibili.py`](scripts/bilibili.py) — self-contained, stdlib only.

```sh
# $SKILL_DIR can point at another skill loaded this turn — anchor on our own
# script, and re-run this at the top of every Bash block (fresh shell each time).
BILI="$SKILL_DIR/scripts/bilibili.py"; [ -f "$BILI" ] || BILI=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/bilibili.py' 2>/dev/null | head -1)
[ -f "$BILI" ] || { echo "bilibili script not found (SKILL_DIR=$SKILL_DIR)" >&2; exit 1; }
python3 "$BILI" whoami                     # who is logged in (mid, name)
python3 "$BILI" articles --limit 20        # my 专栏 articles + stats
python3 "$BILI" article <cvid>             # one article's stats (cv id)
python3 "$BILI" drafts --limit 50          # list saved drafts (aid + title)
python3 "$BILI" status --limit 10          # review state of recent submissions
python3 "$BILI" categories                 # 分类 names accepted by --category
```

Stats come straight from Bilibili: `view` (阅读), `like` (点赞), `reply` (评论),
`favorite` (收藏), `coin` (投币).

## Verify the connection first

```sh
BILI="$SKILL_DIR/scripts/bilibili.py"; [ -f "$BILI" ] || BILI=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/bilibili.py' 2>/dev/null | head -1)
python3 "$BILI" whoami
# → {"mid": 10000000, "name": "...", "level": 4}
```

On a not-logged-in / auth error the cookie is expired — have the user reconnect
at <https://studio.acedata.cloud/console/connectors>. Do **not** loop-retry.

## Publishing — GATED (dry-run unless trailing `--confirm`)

`publish` writes to the user's real account. 专栏 content is **HTML**. Without a
trailing `--confirm` it dry-runs. `--confirm` is honored **only as the last
argument**. Always show the dry-run, get an explicit "yes", then re-run.

```sh
BILI="$SKILL_DIR/scripts/bilibili.py"; [ -f "$BILI" ] || BILI=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/bilibili.py' 2>/dev/null | head -1)
python3 "$BILI" publish --title "标题" --content-file a.html                       # dry-run
python3 "$BILI" publish --title "标题" --content-file a.html --draft-only --confirm   # save a draft
python3 "$BILI" publish --title "标题" --content-file a.html --confirm                # save draft + submit (publish)
python3 "$BILI" publish --title "标题" --content-file a.html --category 数码 --confirm  # pick the 分类
```

- `--draft-only` saves a draft (no submit) — safe; finish/publish in the editor.
  Prefer it when the user has not clearly asked to go public: a submitted
  article enters a review queue this CLI cannot withdraw it from.
- The **submit** (go public) step is frequently rate-limited by Bilibili
  risk-control (HTTP 412). When that happens the CLI reports the saved draft +
  edit URL so the user can publish from the web editor.
- `--category` picks the 分类 (default **数码**, which suits technical posts).
  Run `categories` for the accepted names. The result echoes the 分类 actually
  used as `category` / `category_id` — report it when it wasn't the user's pick.

### Publishing is not instant — it enters a review queue

A successful `submit` returns `state: -2` (**待审核**) and `pending_review: true`.
The returned `url` **404s for everyone until Bilibili approves it** (usually
minutes to hours). Tell the user it is pending; do not claim it is live, and do
not re-submit. Check later with `status`, which is the only view that shows
pending/rejected articles (the public list omits them):

```sh
python3 "$BILI" status --limit 5    # state_desc: 待审核 / 已发布 / 未通过 (+ reason)
```

Other states are **not** pending and will never go live on their own — the CLI
returns them with `ok: false` and `published: false` (`-1` 未通过 rejected, `-3`
锁定, `-4` 已删除). Read `state_desc`, tell the user plainly, and check `status`
for the `reason` rather than re-submitting.

The `id` in the publish result is the **article id** (use `cv<id>`), which is a
different number from `draft_aid`. Only ever share the `url` field. If Bilibili
returned no article id, `url` and `id` are `null` and `id_unverified: true` is
set — there is nothing shareable yet, so find the article with `status` instead
of constructing a link from `draft_aid`.

## Managing drafts (the 999-draft cap)

Bilibili caps 专栏 drafts at **999**; once full, saving a new draft fails with
`code 37106 草稿数已达最大上限`. List drafts and delete the ones you don't need:

```sh
BILI="$SKILL_DIR/scripts/bilibili.py"; [ -f "$BILI" ] || BILI=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/bilibili.py' 2>/dev/null | head -1)
python3 "$BILI" drafts --limit 50                       # list (aid + title)
python3 "$BILI" delete-draft <aid> <aid2> ...           # dry-run (shows what would delete)
python3 "$BILI" delete-draft <aid> <aid2> ... --confirm # PERMANENTLY delete those drafts
```

- `delete-draft` is **GATED** (dry-run unless trailing `--confirm`) and deletion
  is **permanent** — always show the dry-run + the titles and get an explicit
  "yes" before `--confirm`. Pass multiple aids to batch a few per call.
- Never bulk-delete blindly: list first, confirm the titles are junk/duplicates.

## Images

`publish` automatically re-hosts external images (both `<img src>` and markdown)
onto Bilibili's CDN (`i0.hdslb.com` / `article.biliimg.com`) before saving —
Bilibili hotlink-blocks external images and rejects the whole article (`37130`)
if any external link remains. webp sources (which upcover rejects) are
transcoded to png via the CDN when possible; an image that still can't upload is
**dropped** from the article rather than failing the post. `--no-rehost-images`
skips this.

## Gotchas

- **This is the user's real Bilibili account.** Confirm before any publish.
- **submit may 412** (anti-bot) even when the draft saved fine — the draft is the
  reliable result; don't loop-retry submit.
- A 分类 the account can't post to returns `-17`; without `--category` the CLI
  auto-retries the fallback list.
- **Never print `BILIBILI_COOKIES`** — it is full account access.
- **ToS**: acts only on the user's own account with their own captured cookie.


## Record the output

After you successfully publish and obtain the live result URL, call the built-in
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:

```
publish_artifact(kind="article", channel="bilibili", title="<title>", url="<the REAL returned URL>", status="delivered")
```

Use the real returned URL — never fabricate one. That is the `url` field of the
publish result (built from the article `id`, **not** `draft_aid`). Call it once
per published item, only after delivery is confirmed.

- `state: 0` or `1` (已发布, live) → `status="delivered"`.
- `pending_review: true` (待审核) → `status="draft"`; the URL is not live yet.
  Re-record as delivered later if the user asks you to re-check with `status`.
- rejected/locked states, a 412-blocked submit, `id_unverified: true`, or
  `state_unknown: true` → `status="failed"` (or skip it).

See `_shared/artifacts.md`.

Files in this skill

  • SKILL.md8.4 KB
  • scripts/bilibili.py34.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.