# BilibiliHistoryFetcher: archiving a Bilibili viewing history before the site forgets it

> BilibiliHistoryFetcher is a Python and FastAPI service that pulls a user's Bilibili viewing history, interactions, uploads, favourites and comments into a local SQLite database, generates annual summaries, downloads videos and images, and exposes a read-only MCP server so other AI clients on the same network can query the archive. It is MIT licensed and the current release is 1.7.2 from 2026-06-21.

**LifeArchiveProject/BilibiliHistoryFetcher** — 获取b站历史记录，一键下载用户所有的视频，动态，收藏夹，找回14天内b站在屏幕上显示过的图片，生成详细的年度总结，自动化任务，下面链接是对应前端

- Repository: https://github.com/LifeArchiveProject/BilibiliHistoryFetcher
- Website: https://github.com/2977094657/BiliHistoryFrontend
- Stars: 1,227 · Forks: 65
- Language: Python
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/lifearchiveproject-bilibilihistoryfetcher

## The problem is a platform that keeps only three months of history

BilibiliHistoryFetcher is described in the repository as a Bilibili history fetch and analysis tool, and its function list reads like a response to a specific and painful data loss problem.

The project fetches, processes, analyses and visualises a user's Bilibili viewing history data, and it provides a complete data processing flow from acquisition to visualisation, with support for automated runs and email notification. The feature checklist is the clearest statement of the scope: fetching history, annual summaries, video and image downloads including one-click download of all of a user's submitted videos, dynamic posts, scheduled tasks, comments, favourites with batch saving and one-click download of everything in a favourite list, and interaction records.

Two of those lines are the distinctive ones. The project fetches interaction records, meaning favourites, likes and coin tosses, and it does that automatically while fetching history, adding the interaction data into the annual summary analysis. The reason is stated directly: to mitigate the fact that Bilibili viewing history only keeps the last three months. The tool exists because the platform's own retention window is short enough that your own history disappears, and the interaction data is a partial substitute for what has already been dropped.

The other distinctive line is the recovery of images displayed on screen within the last 14 days, which is the most specific capability in the list and the one with the hardest ceiling.

The implementation is Python with FastAPI and SQLite, and the architecture is a backend service with a separate frontend. The backend and the frontend are two repositories, and the compose file wires them together as two services, a backend on port 8899 and a frontend on 5173 mapped to port 80 in the container.

## The deployment path depends on whether you want a GUI or a service

There are several ways to run it, and the documentation leads with the one aimed at people who do not want to install anything.

On Windows there is a no-install path: download the backend executable and the frontend executable from their respective releases pages and double-click both. The backend release page and the frontend release page are separate, and the project explicitly recommends this route.

For a self-hosted service, Docker is the documented path. The prebuilt CPU image is pulled and run like this:

```bash
docker pull ghcr.io/lifearchiveproject/bili-history-fetcher:latest
docker run -d -v ./config:/app/config -v ./output:/app/output -p 8899:8899 --name bilibili-api ghcr.io/lifearchiveproject/bili-history-fetcher:latest
```

Two mounts, and the documentation explains what each is for. The config directory holds the configuration file with the SESSDATA and other settings, and the output directory holds the downloaded videos, images and generated data. The image tags are `latest` or a version tag, and only `linux/amd64` is provided at present.

There is a migration note worth reading, because it is a trap for anyone following an older guide. After the repository moved to the `LifeArchiveProject` organisation, the backend image moved to the `ghcr.io/lifearchiveproject/` namespace, and the old `ghcr.io/2977094657/...` path is a personal namespace that is no longer a recommended install source. The documentation also notes that if pulling from the new namespace gives `denied` or `unauthorized`, the package visibility in GitHub Packages may be Private, since newly published container packages there can default to that, and it has to be made Public for anonymous pulls to work.

For local development, uv is the documented path with `uv sync` followed by `uv run main.py`, and pip works as well with `pip install -r requirements.txt` and `python main.py`. The requirements file is generated by uv from the lock, and the project requires Python 3.10 or newer, SQLite 3 and FFmpeg for video downloads.

## What the interaction recovery actually recovers, and what it cannot

The interaction recovery is the part of the tool with the most nuance, and the documentation is unusually precise about its limits, which is worth preserving.

The favourites API supports pagination and returns `fav_time`, so the system synchronises all accessible favourites content regardless of year. The coin web interface returns the coin time for the records it returns. The like web interface, however, is mostly a list of recently liked videos, and the documentation states that no reliable full-history pagination and like time field has been found.

The user information interface's registration time field is described as usually returning `0` in the current documentation, which means account registration time cannot be relied on as the starting point for a full history.

So the recovery is partial by design, and the project says so. What is complete is favourites, with timestamps. What is partial is coins and likes.

The mechanics of the merge are worth understanding. The supplement records are written into the main history database in one go after the SQLite history import completes, so they appear in the frontend history page marked as interaction supplements with a note recording whether the source was a favourite, a like or a coin. The system detects whether such records already exist in the main history library and records the import state, and once imported, later syncs and scheduled tasks skip it, so nothing is written twice.

Scheduled tasks call the existing history fetch and import chain, which means they trigger the interaction supplement as well. The tool also exposes a data integrity report, which is how you would check whether a given year is complete before drawing conclusions from a summary.

## A read-only MCP server on the LAN, deliberately without write access

The newest thing in the project is a built-in read-only MCP service, and the design decisions in it are the clearest statement of what the authors think the tool is for.

The service reuses the existing FastAPI application rather than running a separate process, and it is served at `http://<服务所在机器IP>:8899/mcp/`, so it is reachable from other machines on the same network. The configuration lives under `server.mcp` in `config/config.yaml`:

```yaml
server:
  mcp:
    enabled: true
    path: "/mcp"
    auth_enabled: true
    max_page_size: 100
```

A client has to send `Authorization: Bearer <token>`, and the token can also be supplied through the `BHF_MCP_TOKEN` environment variable, which the documentation suggests for deployments that would rather not write the token into a config file.

The scope of what MCP v1 exposes is the interesting part. It opens read capabilities only: project status, available years, paginated history queries, history search, annual summaries, viewing behaviour analysis, title analysis, interaction records, video details, scheduled task status and a data health report. Capabilities with side effects are not exposed through MCP, and the list is explicit: sync, download, delete, login, database reset and configuration changes.

There are four built-in resources, `bili://project/overview`, `bili://project/tool-guide`, `bili://project/data-status` and `bili://project/privacy-policy`, the last of which covers privacy, data masking and prohibited operations. The tool list is long and read-only throughout, from `get_project_status` and `list_available_years` through `query_history_records`, `get_annual_summary`, `get_video_detail` and `get_data_integrity_report`.

The MCP dependency itself is in the manifest at `mcp[cli]>=1.27.2`, alongside the FastAPI and uvicorn stack, so the server runs inside the same process as the API.

## Analysis, downloads and a scheduler, with the usual Chinese-language tooling underneath

The dependency list in `pyproject.toml` describes what the project actually does, and it is a data-processing stack rather than a scraper.

For analysis there is `pandas` at ~2.2.3, `numpy` at ~1.26.4, `scikit-learn` at ~1.5.2 and `pyecharts` at ~2.0.8 for the charts, with `snownlp` and `jieba` for Chinese text processing, which is what you would expect for a tool that analyses Chinese video titles. `openpyxl` handles spreadsheets, `python-dateutil` handles dates, and `qrcode` and `pillow` handle images. For fetching, `aiohttp`, `httpx` and `requests` cover HTTP, and `yutto` at ~2.0.0 is the Bilibili downloader the project builds on, which is why the requirements file shows `biliass` and `dict2xml` pulled in through yutto. For operations there is `schedule` for the cron-like tasks, `apprise` for push notifications, `psutil` for system metrics, `loguru` for logging, `pydantic` for the data models, `uvicorn` as the server, and `pyinstaller` at >=6.12.0 for the packaged executable.

The top-level files line up with that. There is `main.py` as the entry point, `mcp_server.py` for the MCP service, `app_launcher.py` and `app.spec` for the PyInstaller packaging, `build.py`, a `routers/` directory for the FastAPI routes, `config/`, `scripts/`, `tests/`, a `skills/` directory, and `docker/` with the CPU Dockerfile the build instructions reference.

Notifications are configured in the settings page with both email and Apprise push, and `config/config.yaml` takes a list of Apprise URLs under `apprise.urls`, one per line. The documentation says that a scheduled task error and an expired SESSDATA both trigger an email and an Apprise push at the same time, which is a sensible design: the two most common ways this tool breaks are a task that stopped running and a session cookie that went stale, and both deserve a notification rather than a silent gap in the archive.

## Migration is one directory, and where this tool is the wrong choice

The data migration guidance is short and worth repeating, because it tells you what the tool treats as data and what it treats as configuration.

The core conclusion is that migrating requires copying the whole `output` directory to the new environment. The scenarios covered are same-machine path migration, cross-machine migration, Docker and Compose deployment, and the packaged or local run. The steps are to stop the running service, back up the entire `output` folder, place it in the new environment as `./output` for a local run, mount it at `/app/output` for Docker, or put it next to the executable for the packaged version, then start the service and verify that the history, statistics and visualisations all display.

The note at the end is the important one: authentication information and runtime configuration live in `config/` and are not part of data migration, so the new environment needs `config/config.yaml` filled in as required, including the SESSDATA.

So the data is portable and the credentials are not, which is the correct split and means a backup of `output` is a real backup of the archive.

Where this tool is the wrong choice has three parts. The first is a full-fidelity archive. The interaction recovery is partial by the project's own account, the like history has no reliable pagination, and the images shown on screen are capped at 14 days. If your requirement is a complete record of an account's activity, this does not provide it.

The second is anything multi-user. The design is a single set of credentials, one SESSDATA, one `config.yaml`, one `output` directory. There is no user model and no separation between accounts, and the MCP endpoint is documented as LAN-reachable and read-only, which is a protection boundary rather than an access model.

The third is the legal and platform side. Downloading someone's videos, and batch saving favourites, is subject to the platform's terms and to the rights of the people in the video, and the annual summary feature publishes viewing behaviour. The project is explicit that it is for one's own data and for the users who consent, and the `bili://project/privacy-policy` resource documents the masking and the prohibited operations. Whether a given use is appropriate is a question about the accounts involved rather than about the software, and the tool's read-only MCP design is a good reason to keep it that way.

The project is MIT licensed, the repository is not archived, the last push was on 2026-06-26, and the release line is current with v1.7.2 from 2026-06-21.

## Conclusion

BilibiliHistoryFetcher fits a researcher or archivist who needs a durable copy of their own or a consenting user's Bilibili activity before the platform's own retention window removes it, and it fits a team that wants the same archive reachable by an AI assistant over the local network. It does not fit anyone who expects a full-fidelity archive, because the interaction recovery is explicitly partial and the image recovery is capped at 14 days. Before you rely on it, put your own token in `config/config.yaml`, keep the `output` directory under version control or a backup, and check the read-only scope of the MCP endpoint, since it is reachable on the LAN by design.

## FAQ

### What does BilibiliHistoryFetcher actually collect?

It fetches a user's Bilibili viewing history, interaction records such as favourites, likes and coins, submitted videos, dynamic posts, comments and favourite lists into a local SQLite database, then produces annual summaries and downloads videos and images. The interaction supplement exists because Bilibili viewing history only keeps about three months.

### How do I run BilibiliHistoryFetcher with Docker?

Pull `ghcr.io/lifearchiveproject/bili-history-fetcher:latest` and run it with the config and output directories mounted and port 8899 published. The image is currently only built for `linux/amd64`, and the compose file adds a frontend service on port 5173.

### What can the MCP server in BilibiliHistoryFetcher do?

It exposes read-only capabilities over the LAN at the `/mcp` path, including project status, history queries and search, annual summaries, viewing and title analytics, interaction records, video details, task status and a data integrity report. Sync, download, delete, login, database reset and configuration changes are deliberately not exposed.

### How do I move BilibiliHistoryFetcher to another machine?

Stop the service, copy the whole `output` directory to the new environment and place it as `./output` locally, mount it at `/app/output` in Docker, or place it beside the executable in the packaged version. The `config` directory is not data and has to be recreated, including the SESSDATA.

## Sources

- [License: MIT](https://github.com/LifeArchiveProject/BilibiliHistoryFetcher/blob/master/LICENSE)
- [LifeArchiveProject/BilibiliHistoryFetcher on GitHub](https://github.com/LifeArchiveProject/BilibiliHistoryFetcher)
- [Project website](https://github.com/2977094657/BiliHistoryFrontend)
- [README](https://github.com/LifeArchiveProject/BilibiliHistoryFetcher/blob/master/README.md)
- [Releases](https://github.com/LifeArchiveProject/BilibiliHistoryFetcher/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/lifearchiveproject-bilibilihistoryfetcher
