web-scrobbler: four stores, a Safari build that needs Xcode, and a lint step for cycles
Scrobble music all around the web!
At a glance
- What is it?
- Web Scrobbler is a browser extension that records what you listen to into one of five scrobbling services, two of them large global ones and three of them small, independent or federated. What the repository shows is a project with unusually careful release discipline for something distributed as a bundle: exact version pins, two separate type-check configurations, five parallel lint passes including one that fails on dependency cycles, and a privacy policy that is a localised string shipped inside the extension rather than a page hosted elsewhere.
- Who is it for?
- Install this if you listen in a browser and want that history recorded somewhere you can query later, and pick the store that matches your browser, with Opera handled through a bridge rather than natively. Two things to weigh before you install it anywhere sensitive.
- 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 7 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 9, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Four stores, and a bridge for the browser that has none
The installation section is really a routing table, and it is worth reading as one. Chrome users install from the Chrome store listing. Firefox users install from the add-ons site. Safari users install from the Apple store. Edge users install from the Edge add-ons site. Then there is Opera, which is the interesting case: the page sends Opera users to install a third-party addon whose entire purpose is to let them install an extension from the Chrome store. That is not a workaround the project chose; it is the shape of that ecosystem, since there is no first-party store listing for it. The practical consequence is that an Opera user is running something written for a different browser through a translation layer, and the project documents the route rather than pretending the extension is native there. Everything else is symmetric, which is what you would expect from a bundle that compiles down for four browsers from one source.
One build command, three targets, and one of them needs a Mac
The development section gives you a single command and three arguments:
# Build the extension
> npm run build firefox
# or
> npm run build chrome
# or (requires Xcode (xcrun and xcodebuild))
> npm run build safariDependencies are installed first, and the built bundle lands in a build directory you can load. The Safari line carries a note in the comment that it requires Xcode and two of its command line tools. Everything else in this repository is platform-neutral, but the Safari target is not, and the checkout says so twice over: there is an Xcode project directory in the root and a separate shell script alongside the release script. So a continuous integration runner on a Linux machine can produce three of the four store artefacts and not the fourth, and the fourth is the one whose review queue you cannot influence. For a contributor that means testing a change across all four stores requires access to a Mac, which is worth knowing before you pick this as a weekend project.
Installing from a checkout is two different procedures with two names
Building from source is one paragraph. If you are on Chrome the page sends you to the browser's own documentation for loading an unpacked extension, which is where the compiled bundle goes: the readme says the output lands in a build directory and that you point the browser at that directory. If you are on Firefox it sends you to a wiki page about installing a temporary add-on instead. Those are the same idea in two ecosystems with two different vocabularies, and the project handles it the right way, by linking each separately instead of pretending they are the same thing. The extension is also installable as a zip file, so if you are reviewing a change rather than building it, the two wiki pages are the difference between a working local install and a confusing afternoon.
The privacy policy is a localised string inside the extension
The privacy link in the readme is not a web page. It resolves to a markdown file inside the source tree, in the English locale directory, which means the text is versioned with the code and shipped as part of the extension's own localised messages. That is a better arrangement than the common one of a policy hosted separately on a site, for two reasons. The disclosure that ships to users and the file a reviewer can read in the source are the same file, so they cannot drift apart between a release and a web page. And it is translated alongside everything else, so the policy a non-English user reads is not a stale copy. The translations work the same way: a dedicated command pulls only the translated strings from the translation platform and then runs a preparation script over them, rather than translators committing files to the repository.
Five linters run in parallel, and one of them looks for dependency cycles
The lint command is not a single tool. It runs five checks at once: the JavaScript linter, a stylesheet linter over the Sass files, a formatter check, a markdown processor, and a tool that reports circular dependencies in the source tree. Four of those are ordinary housekeeping, and a project of this size can justify all of them because the content is code, styles, prose and translations in one repository. The fifth is the interesting one. An architecture built out of pluggable connectors is exactly the shape of project where a cycle between two connectors compiles cleanly and then fails at run time in somebody's browser, and catching that as a lint failure rather than as a bug report is the right place to catch it. Running it as part of the default lint rather than leaving it to continuous integration says the project treats dependency direction as a review concern.
Two compiler configurations, because connectors are not the extension
There are two TypeScript configurations in the root and the type-check command runs both, one for the project and one named for connectors. That split only makes sense if connectors are permitted to be code the project does not control, which is consistent with everything else on the page: developing connectors gets its own wiki page, it is mentioned separately from the extension's own features, and the extension bundles a cross-browser API shim so that third-party code has one surface to target. So there is an explicit seam. The extension is strict about itself, and deliberately more forgiving about what plugs into it. Two smaller details in the same area are worth noting for anyone setting up: the node version is pinned in the conventional file so a contributor's runtime matches the one the builds use, and git hooks are installed from the manifest's prepare step, so a fresh clone has them before your first commit.
Two build tools sit in the runtime dependency list, and every version is exact
The runtime dependency list has five entries and every one is pinned to an exact version with no range at all. Among them are a digest library, which is the shape you need when a service requires a digest of a shared secret in the request, a cross-browser extension API shim, a first-party package for filtering track metadata, and two tools that would normally sit on the other side of the line: the bundler and the stylesheet linter. Putting build tooling in the runtime set costs nothing for an extension that ships as a compiled bundle, but it makes the dependency list read as a description of what the tool is rather than what it needs at run time. The exact pinning is the deliberate trade in the other direction. For something that has to clear four extension stores, each with its own review and its own idea of what changed, a build you can reproduce beats one that quietly picks up a patch release.
Editorial conclusion
Install this if you listen in a browser and want that history recorded somewhere you can query later, and pick the store that matches your browser, with Opera handled through a bridge rather than natively. Two things to weigh before you install it anywhere sensitive. The extension runs in the page you are listening on, so what it can read is bounded by what you grant the store listing, and the project publishes its privacy text as a file inside the extension rather than on a page, which makes it easy to audit in the source. And if you are thinking about contributing, note that the Safari target cannot be built off a Mac, which constrains how you test your change against all four stores. The default branch was last pushed on 2026-10-03 and the newest release is v3.23.1 from 2026-09-18.
Frequently asked questions
what is web scrobbler
A browser extension that helps online music listeners scrobble their playback history, meaning it records what you listened to and sends it to a scrobbling service. It supports five services, and it is published to four extension stores: the Chrome store, the Firefox add-ons site, the Apple store for Safari and the Edge add-ons site, with Opera users installing it through a bridge addon that pulls it from the Chrome store.
what does web scrobbler do
It records playback from the music services you listen to in the browser and writes that history to one of five supported services: two large global ones and three smaller, independent or federated ones. It can also be installed unpacked from a build directory, and its development model treats site support as pluggable connectors with their own documentation and their own type-checking configuration.
how to use web scrobbler
Install it from the store that matches your browser, then sign in to whichever service you want your history recorded against, from the extension's own options. If you are installing from a checkout instead, build it with the command for your target, then load the output directory as an unpacked extension on Chrome or as a temporary add-on on Firefox, following the separate wiki page for each.
is web scrobbler safe
The repository's answer to that is its privacy text, and the text is not hosted on a website. It is a markdown file inside the source, in the English locale directory, which means it is versioned with the code and shipped as part of the extension's own localised messages. Nothing else is asserted about safety anywhere in the readme, so the file and the permissions the store listing asks for are what you have to read.
why is web scrobbler not working
The readme does not contain a troubleshooting section, so it cannot answer that, and there is no issue-template symptom list on the page either. What it does point you to is the project's chat channel and the wiki, plus a dedicated page on developing the connectors for individual sites, which is where a site-specific failure would be handled. If you are filing a problem, the connector documentation is the fastest route to a diagnosis.
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/web-scrobbler-web-scrobbler)