RSSWorker turns Bilibili, Weibo, Telegram and Xiaohongshu into RSS feeds
运行在Cloudflare Worker上的RSS订阅生成器
At a glance
- What is it?
- RSSWorker is a lightweight RSS subscription generator that runs on Cloudflare Workers, with one route per platform under a /rss/ prefix. It is small enough to fit the free Workers bundle limit, which pushes the design towards fetch and HTMLRewriter rather than a browser, and it is MIT licensed with no releases.
- Who is it for?
- Teams that want RSS feeds for Bilibili, Telegram, Weibo or Xiaohongshu content and already run on Cloudflare should try RSSWorker, because it costs nothing to run, deploys with a single button and keeps the whole generator inside the Workers size budget. It is the wrong tool if you need a broad catalogue of sources, since the route list is five platforms, and it is the wrong tool if your Weibo or Xiaohongshu access depends on a session that will expire.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 67 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A feed generator sized to fit the Workers bundle limit
RSSWorker is a lightweight RSS subscription tool that can be deployed on Cloudflare Workers. The repository description is the same sentence in Chinese, and the topics confirm the scope: bilibili, rss, rss-generator, telegram, weibo and xiaohongshu.
The interesting constraint is stated in the development notes. Cloudflare Workers have a maximum packaged size limit, one megabyte for free users and ten megabytes for paying users, so plugins need to be as lightweight as possible. The README suggests using fetch for requests and the HTMLRewriter provided by Cloudflare Workers for HTML parsing.
That single constraint explains most of the design. There is no headless browser, no bundled HTML parser with a large dependency tree, and no attempt to be a general purpose scraping platform. The worker fetches a page and reshapes it, and the package list in package.json backs this up: hono for the HTTP layer, mustache for the feed templates, dayjs for dates, node-forge and hpack and http2 and runes2 for the protocol level work that the Telegram route appears to need, and a set of bufbuild packages for the connect RPC stack.
The project is MIT licensed, and it credits RSSHub for inspiration and part of the code, with a Japanese web hosting sponsor listed under acknowledgements. The audience is self-hosters who want a private feed endpoint for platforms that do not offer one, and who would rather not run a container for it.
Five routes, all under the same prefix
The route table is small and explicit, and every route lives under a domain prefix, so a deployment at example.com exposes feeds at paths like https://example.com/rss/bilibili/user/dynamic/1.
The supported routes are bilibili user dynamic at /bilibili/user/dynamic/:uid, bilibili user video at /bilibili/user/video/:uid, telegram channel at /telegram/channel/:username, weibo user at /weibo/user/:uid, and xiaohongshu user at /xiaohongshu/user/:uid.
That list is the functional surface of the project, and it is worth reading as a decision about scope. Three of the five routes are per-user feeds on Chinese social platforms, one is a Telegram channel, and none of them is a generic feed of arbitrary pages. The parameters are identifiers: a bilibili uid, a telegram channel username, a weibo uid, a xiaohongshu user id.
The structure also tells you how the code is organised. The development instructions say to add a script in src/lib/[site name]/[feature] by following an existing demo, and then to add the plugin in src/route.js. So the platform adapters are grouped by site and feature under src/lib, and src/route.js is the dispatch table that maps the URL prefix to the adapter.
A reader can therefore tell what it would cost to add a source: one script in a directory named after the site, and one line in the routing file.
Two platforms need a session: the Weibo cookie and the Xiaohongshu id
The README is candid about the fact that two of the routes do not work out of the box, and both cases come down to a platform change.
The first is Xiaohongshu. After the platform updated, the old xiaohongshu account number can no longer be used and the user id is required instead. The README gives the acquisition method: on mobile, go to the user page, open the three dots in the top right, choose copy link and take the user id from the copied link; on the web, the id is in the page URL, in the form https://www.xiaohongshu.com/user/profile/5d2aec020000000012037401.
The second is Weibo, which after its update needs a cookie. The README references the RSSHub deployment documentation for the details and then gives the procedure: log in to Weibo, take the uid from the URL of your personal homepage and append it to https://m.weibo.cn/api/container/getIndex?type=uid&value=, open the developer console with F12, switch to the Network panel, switch to any followed group and open the first request captured, where the request path should contain /feed/group, then look at the request headers, find the Cookie field and copy its content. Finally, in the command line you type wrangler secret put WEIBO_COOKIE, press enter, paste the copied cookie and press enter again.
That last step is the one to note for an evaluator. The cookie is stored as a Worker secret through wrangler rather than in the configuration, which is the right place for it, but it also means the Weibo route depends on a session that the user must maintain. Nothing in the README describes automatic refresh.
Adding a platform means one script and one routing entry
The template that a new plugin follows is given in the README, and it is a plain JavaScript object rather than a framework abstraction. The feed model has a title, a link, a description, a language, a category and a list of items, and each item carries a title, link, description, pubDate, guid, author, category, comments, an optional enclosure with a url, type and length, and a source object with a title and url.
let items = [
{
title: 'Bilibili User Dynamic',
link: `https://space.bilibili.com/${uid}/dynamic`,
description: 'Bilibili User Dynamic233',
pubDate: new Date().toUTCString(),
guid: `https://space.bilibili.com/${uid}/dynamic`,
author: '[email protected]',
category: 'video',
comments: `https://space.bilibili.com/${uid}/dynamic`,
enclosure: {
url: 'https://www.bilibili.com/favicon.ico',
type: 'image/x-icon',
length: 0,
},
source: {
title: 'Bilibili',
url: 'https://www.bilibili.com',
},
},
];The interesting fields are the ones a feed reader actually uses. The guid is a stable string, and here it matches the link, which is what stops a reader treating every rebuild as a new item. The enclosure carries a media type and a length, which is how an audio or video attachment is advertised, and the source object identifies the upstream site so that several feeds can share a reader.
Because the model is plain data, a plugin is a function that fills in an array of items and hands back the feed object, and the surrounding machinery deals with rendering. There is no plugin API to learn, which is the point.
Wrangler drives the whole lifecycle, and a patch step runs on install
The package.json scripts show the whole workflow in four lines. The build script runs a dry-run deploy, the deploy script runs the real deploy, and both start and dev run wrangler dev for local development.
"build": "wrangler deploy --dry-run",
"deploy": "wrangler deploy",
"start": "wrangler dev",
"dev": "wrangler dev",
"postinstall": "patch-package"That last entry is the one that tells you something about the project. patch-package runs automatically after install, and the repository carries a patches directory. That means the project applies patches to its dependencies at install time, which is how a Worker project fixes behaviour inside a dependency without forking it. The cost is that a fresh clone does not install cleanly without the patch step running, and the patched dependency versions are pinned by the patch files rather than by the manifest alone.
Deployment is one click for the people who do not want a command line. The README carries a Deploy to Cloudflare Workers button that points at the repository, and the wrangler.toml file at the root is the configuration the deploy and dev scripts both read.
The dependency versions are current, with wrangler at 4.94 and hono at 4.12, and the package itself is marked private with version 0.0.0, which is the usual way to say that the repository is an application rather than something you publish to a registry. There is a test directory at the root and a .prettierrc, and the sources live under src.
Where RSSWorker is the wrong tool
The limits are a direct consequence of the scope, and they are worth being concrete about.
The route list is five entries. Anyone who needs a feed from a platform that is not on that list gets nothing from this project, and the README's own acknowledgement of RSSHub points at where the broader catalogue lives. The two are complementary rather than competing: this worker is small enough to run on the free tier and covers a handful of Chinese platforms, while the upstream project it credits is where a much larger set of routes is maintained.
The session dependency is the second limit and it is the one that bites in production. The Weibo route needs a cookie that a human copies by hand out of a browser developer console, and the Xiaohongshu route needs a user id that changes when the platform changes its URL format. Both are breakable by a platform update, and neither is documented as self-healing. For a personal feed that is fine; for a service other people depend on, it is a recurring maintenance task with a silent failure mode, because a stale cookie produces an empty feed rather than an error.
The third limit is the bundle ceiling. One megabyte on the free tier is generous for a fetch-and-reshape worker and completely inadequate for anything that wants a real browser or a full HTML parser, which is exactly why the README steers towards HTMLRewriter. If your feed needs JavaScript rendering, this design does not reach it.
Finally, the release story is thin. The repository publishes no GitHub releases, the package version is a placeholder 0.0.0, and the last push was on 2026-08-18. Anyone deploying it is deploying a branch, not a version, and should expect to pull upstream changes themselves.
Editorial conclusion
Teams that want RSS feeds for Bilibili, Telegram, Weibo or Xiaohongshu content and already run on Cloudflare should try RSSWorker, because it costs nothing to run, deploys with a single button and keeps the whole generator inside the Workers size budget. It is the wrong tool if you need a broad catalogue of sources, since the route list is five platforms, and it is the wrong tool if your Weibo or Xiaohongshu access depends on a session that will expire. Before deploying, read the platform notes about the Weibo cookie secret and the Xiaohongshu user id, and check the route list in the README against the sources you actually need.
Frequently asked questions
Which platforms does RSSWorker support?
The README lists five routes: bilibili user dynamic, bilibili user video, telegram channel, weibo user and xiaohongshu user, all under the /rss/ prefix of the deployed domain, such as https://example.com/rss/bilibili/user/dynamic/1.
Why does the Weibo feed need a cookie?
Because Weibo changed and the route now requires a session. The README explains how to find the cookie in the request headers of a captured /feed/group request and then to store it with wrangler secret put WEIBO_COOKIE, so the value is kept as a Worker secret rather than in configuration.
How do I add a new feed source?
Add a script under src/lib/[site name]/[feature] following an existing demo, then register the plugin in src/route.js. The feed template is a plain JavaScript object with a list of items and a feed level title, link, description, language and category.
Why do my plugins have to be so small?
Cloudflare Workers limit the packaged size, one megabyte for free users and ten megabytes for paying users. The README says plugins should stay lightweight and suggests using fetch for requests and the HTMLRewriter provided by Cloudflare Workers for HTML parsing.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/yllhwa-rssworker)Was this useful?