galaxy-downloader parses a pasted link, then does the work in your browser
Bilibili、抖音、小红书等平台下载视频和音频。
At a glance
- What is it?
- galaxy-downloader is a vinext application that resolves media links from Bilibili, Douyin, TikTok, X, Telegram and a couple of dozen other platforms into downloadable video, audio or images. The interesting part is where the heavy lifting happens: audio extraction runs through FFmpeg.wasm in the browser, so the download never touches a server-side transcode.
- Who is it for?
- galaxy-downloader suits a self-hoster or a privacy conscious user who wants to keep a personal archive of public media, and it fits a developer who wants a readable example of a vinext application with a separate public API base and an explicit SEO policy.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A vinext app built around one input box
The whole user flow fits in five steps, and the README states them plainly: copy the media link, paste it into the input box, click the parse button, choose video, audio or images, and wait for the file to save. That is the entire product surface, and it is why the project can cover so many platforms without a native client for each one. The application is a Next.js App Router compatible project running on vinext, the Cloudflare framework that produces a `dist/` build, and the source tree is TypeScript with React 19 and Tailwind CSS. The package manifest still carries the name `bilibili-audio-downloader` at version 2.0.0 even though the feature set now reaches far past Bilibili, which tells you the project grew by accretion rather than by redesign. For a user, the appeal is that one text field handles Bilibili video and audio, Douyin video and image posts, Instagram Reels, Xiaohongshu notes, TikTok, X, Telegram, Threads, WeChat official accounts, Weibo, Niconico, Vimeo, Dailymotion, Streamable, Reddit, Newgrounds, Tumblr, Pinterest, VK, OK.ru, Twitch, SoundCloud and Apple Podcasts.
The front end talks to a separate public API
Link resolution is not done in the page. The front end sends its fetch requests to a base address held in the `NEXT_PUBLIC_API_BASE_URL` environment variable, and the documented example is `https://downloader-api.bhwa233.com`. When that variable is missing during local development, the application falls back to `http://localhost:8788`, so a developer running the front end alone will see requests aimed at a port that nothing is listening on until a separate API service is up. This split is the single most important architectural fact about the project, because it means the parsing logic lives somewhere you cannot read in this repository, and the deployment you run is only half the system. Two other variables matter at build time. `NEXT_PUBLIC_SITE_URL` sets the site base, and if it is not configured locally the app uses `http://localhost:3010` instead, which the README describes as a guard against manifest, canonical and Open Graph links pointing at the production domain. `SEO_INDEXABLE` decides whether search engines may index the deployment.
Indexing policy is decided by environment, not by a flag you remember to pass
The default indexing rules are worth reading closely, because they are the kind of detail that only shows up in a README that has been deployed. On a Vercel production environment indexing is allowed automatically, on a Vercel preview environment it is denied by default, and anywhere else the decision falls back to checking whether `NODE_ENV` equals `production`. `SEO_INDEXABLE` overrides all of that when it is set. The practical effect is that a self-hosted instance running in production mode is indexable unless you intervene, while a preview build is not, which is what you want for a staging copy of a public download page. The README also asks operators to watch Search Console index counts, the `sitemap.xml` submission status, Core Web Vitals and the `hreflang` and canonical agreement across the multilingual pages, since the interface is translated into Simplified Chinese, Traditional Chinese, English, Japanese, Spanish and Russian.
Audio extraction runs in the browser through FFmpeg.wasm
This is where the design is unusual. Instead of posting the file to a server and transcoding it there, the project uses FFmpeg.wasm to do the audio work in the browser, and the README is upfront that audio extraction is currently handled mostly on the client side, which makes it subject to browser performance and file size. That is a real constraint: a long video is a heavy CPU job in a tab, and the machine doing the extraction is the machine doing the viewing. Two supporting libraries show up in the dependency list. `jszip` handles image posts, which the documentation says can be downloaded separately by platform result or packaged into a zip. `hls.js` and `hls-parser` cover the streaming manifests that some of these platforms serve. The dependency list also carries `browser-fs-access`, which points at the file system access path rather than the older download attribute trick, and the package scripts keep `@ffmpeg/core` pinned at 0.12.9 with a `prepare:ffmpeg-core` step that syncs that core before anything else runs.
Running it locally takes three pnpm commands
The local development section is short, which is a good sign for a project that has to be maintainable while supporting so many platforms. Clone the repository and install the dependencies:
pnpm installThen start the development server:
pnpm devThe `dev` script in the package manifest is worth reading, because it does more than start a server: it runs the FFmpeg core preparation first and then launches vinext on port 3010, which is the port the README tells you to open at http://localhost:3010. The build and start scripts follow the same pattern, with the build running the core preparation and then `vinext build`, and the start command running `vinext start` against the result. The scripts use pnpm 11.8.0 as the declared package manager, and the tree carries both a `pnpm-lock.yaml` and a `package-lock.json`, so pick one and stick to it. The project also has a test suite wired up through vitest, with `pnpm test` running `vitest run` and a `pretest` hook that prepares the FFmpeg core first.
Deployment runs through vinext, not through wrangler directly
The README is unusually firm about one thing: do not use `wrangler deploy` as the deployment command. The project is built on vinext, so the deploy script generates the required configuration, builds, and calls Wrangler itself. The `pnpm deploy` script prepares the FFmpeg core and then runs `scripts/deploy-with-retry.mjs`. That script backs off and retries only on the Cloudflare API rate limit error with code `971`, at 60, 120 and 180 second intervals, and it fails immediately on any other error so that a broken configuration is not hidden behind a retry loop. The number of attempts and the base wait can be changed with `CF_DEPLOY_MAX_ATTEMPTS` and `CF_DEPLOY_RETRY_DELAY_MS`. Two variants exist: `pnpm deploy:ci` for platforms that already ran `pnpm build`, and `pnpm deploy:preview` for preview deployments, and the manifest also exposes a `deploy:dry-run` script that stops short of touching the network. The `wrangler.jsonc` file at the top level is where the Worker configuration lives.
A source available licence that forbids the obvious business model
The licence is the decision that shapes everything else about this project. The README states that the original material uses a custom galaxy-downloader personal use and free public service licence, that the terms live in the `LICENSE` file at the top of the tree, and that this is a source available licence with commercial use restrictions which is not an OSI defined open source licence. Personal non commercial use, study, research and further development are allowed, as is offering a free non commercial download service to the public, including the browser client file transfer that service requires. Modifications need not be published, but a modified build is limited to the person who made it: no source, package, container image or standalone deployment of a modified version may be released to anyone else. Charging, advertising, paid membership, commercial product integration and any use inside a business all require written permission from the copyright holder. The one clause that cuts back the other way is about third party code: `@ffmpeg/core 0.12.9` is declared GPL-2.0-or-later while `@ffmpeg/ffmpeg` and `@ffmpeg/util` are MIT, and the README says the promise that modified source need not be published does not exempt you from those obligations.
Where the tool deliberately stops
Several boundaries are stated rather than discovered, and they are worth reading before you build anything on top of it. For Apple Podcasts, only publicly accessible audio is supported, and the documentation says the tool does not bypass paid access, subscriptions, regional limits, logins or DRM, and it offers no full podcast archive download and no audio extraction for that platform, only the individual episode. Audio extraction elsewhere is browser bound, so file size and browser performance set the practical ceiling. Image and text posts are returned per platform and can be downloaded individually or as a package. The repository publishes no GitHub releases, so versions are not tagged in the way a package registry would tag them, and the last push was on 2026-10-10, which tells you the tree moves but gives you no changelog to read. For platform coverage, the accepted link formats are documented per platform, including short link forms such as `https://b23.tv/...` for Bilibili and `https://v.douyin.com/...` for Douyin, so a link outside those shapes is the first thing to suspect when parsing fails.
Editorial conclusion
galaxy-downloader suits a self-hoster or a privacy conscious user who wants to keep a personal archive of public media, and it fits a developer who wants a readable example of a vinext application with a separate public API base and an explicit SEO policy. It does not fit anyone who needs a commercial download service, because the custom galaxy-downloader licence is source available and non commercial, and it does not fit anyone who needs paid, subscription, region locked or DRM protected media, since the documentation states those cases are not bypassed. Before you commit to it, check three things: whether the public API behind `NEXT_PUBLIC_API_BASE_URL` is one you control, because the front end only requests it and never parses a link by itself; whether the `pnpm dev` path works on your machine, since the dev script prepares the FFmpeg core before starting the server on port 3010; and which licence your deployment falls under, since the terms forbid republishing a modified build.
Frequently asked questions
How do I run galaxy-downloader locally?
Clone the repository, run `pnpm install`, then `pnpm dev`, which prepares the FFmpeg core and starts vinext on port 3010. The README tells you to open http://localhost:3010 in the browser.
Can I use galaxy-downloader to download paid or DRM protected media?
No. The documentation states that the tool does not bypass paid access, subscriptions, regional restrictions, logins or DRM, and for Apple Podcasts it only handles publicly available audio.
Can I run galaxy-downloader as a paid service?
The custom licence permits personal non commercial use and free non commercial public download services. Charging, advertising, paid membership, commercial product integration and business use all require written authorisation from the copyright holder.
Which environment variables does galaxy-downloader need?
`NEXT_PUBLIC_API_BASE_URL` points the front end at the public download API and falls back to `http://localhost:8788` locally, `NEXT_PUBLIC_SITE_URL` sets the site base and defaults to `http://localhost:3010` locally, and `SEO_INDEXABLE` overrides the default indexing decision.
Why does the galaxy-downloader deployment fail when I use wrangler deploy?
The README says not to use `wrangler deploy` as the deployment command, because the project runs on vinext and the deploy script generates the required configuration, builds and then calls Wrangler. Use `pnpm deploy`, `pnpm deploy:ci` or `pnpm deploy:preview` instead.
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/bhwa233-galaxy-downloader)Was this useful?