# freetar: an ad-free frontend for Ultimate Guitar tabs

> freetar is a small Python web application that pulls guitar tabs from Ultimate Guitar and serves them through its own interface, with caching, session-only favourites and no account. It suits self-hosters who want a plainer tab reader and can accept that all upstream data still comes from Ultimate Guitar.

**kmille/freetar** — freetar  - an alternative frontend to ultimate-guitar.com

- Repository: https://github.com/kmille/freetar
- Stars: 785 · Forks: 55
- Language: HTML
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/kmille-freetar

## A tab reader for Ultimate Guitar that asks for no account

freetar exists to give guitar players a plainer way to look up chords and tabs than the one ultimate-guitar.com serves. The project documentation draws the analogy directly: it describes itself as being like Invidious, but scoped to a single site, Ultimate Guitar. That framing explains both the ambition and the ceiling of the tool. It is not a general web proxy and it does not host tab content of its own. It is a rendering layer over one upstream source.

The interface is deliberately plain. The documented feature list spells out the trade: no ads, no popups, no AI and no blockchain, described as "just a simple design". Around that core sit the things a practice session actually needs: search for tabs and view them, toggle chords on and off, dark mode, automatic scrolling, and a layout that is useful for printing a chart onto paper. There is also a WakeLock API call that keeps the screen from turning off while a slow song is on screen, which is a small detail that only makes sense for someone who has actually held a phone over a guitar.

Favourites are the other half of the feature set. You can save chords you like and come back to them, and no account is needed. The catch, which the documentation is explicit about, is that favourites live in session storage and are never sent to the server. That single design decision shapes how you should think about the whole project, including caching, privacy and deployment.

## How freetar fetches, parses and caches tab data

The dependency list in pyproject.toml shows the shape of the pipeline. Flask serves the pages, waitress is the production server, beautifulsoup4 does the HTML parsing, and requests is pinned with the socks extra so that traffic can be routed over a SOCKS proxy. flask-caching and flask-minify sit alongside them for response caching and asset compression. In other words, freetar is a server side scraper that pulls pages from Ultimate Guitar, extracts the tab data with a CSS selector and HTML parser, and re-renders it through its own Jinja templates in freetar/templates.

Caching is the configurable heart of that pipeline, and it is controlled entirely by environment variables. `FREETAR_CACHING` selects the mode: `ram` is the default and keeps tabs in memory, `off` disables caching for development and debugging, and `disk` writes a cache to disk. Two more variables tune it. `FREETAR_CACHE_TIMEOUT` sets how long tabs stay in the cache, and its default of 0 means the timeout is effectively infinite, so a cached tab is reused rather than fetched again. `FREETAR_CACHE_DIR` sets where the disk cache lives and defaults to /tmp.

The practical consequence is that caching is not only a speed feature but also a courtesy feature towards the upstream site. The documentation states plainly that the timeout reduces the requests made to Ultimate Guitar, which matters because the app depends on that site for every tab it shows.

## Three install paths: pip, Docker, and a local checkout

There is a PyPI package, so a local install is a single command, and the result is an executable called `freetar` placed on your PATH. Running it with no arguments makes it listen on 0.0.0.0:22000, which is worth noting because a server that binds to all interfaces by default is exposed to whatever network reaches it.

The pip route from the documentation is:

```bash
pip install freetar
```

The Docker route pulls a prebuilt image and maps the port to localhost only:

```shell
sudo docker pull kmille2/freetar
sudo docker run -p 127.0.0.1:22000:22000 kmille2/freetar
```

The compose file in the repository does the same thing with a published image and a local build context, and it hardens the container by dropping all capabilities, marking the filesystem read only and adding no-new-privileges. The documented compose workflow is:

```shell
sudo docker compose up -d
```

Two compose details matter. The published port comes from `${FREETAR_PORT:-22000}`, so the host port follows the same variable name as the app itself. And if you switch to disk caching, the documentation notes that the mounted directory has to be owned by uid and gid 1000 to match the unprivileged `freetar` user created in the Dockerfile. Building from the checkout instead of pulling is the same file with a build step in front:

```shell
docker compose build
docker compose up -d
```

For local work on the code, the project uses uv, and the documented development commands are:

```bash
FREETAR_CACHING=off uv run freetar/backend.py  # dev server
FREETAR_CACHING=off uv run freetar # production server
```

In that mode the static files live in freetar/static and the HTML templates in freetar/templates, and you open localhost:22000 in the browser. Setting `FREETAR_CACHING=off` during development is deliberate: it forces each request to go upstream, so you see the current response from Ultimate Guitar instead of a stale cached copy.

## Favourites stay in session storage and never reach the server

The favourites system is the part of freetar most likely to surprise you, and the documentation does not hide it. Saved chords are stored in session storage, which the README states is not sent to the server, and no account is required to use them. The practical effect is that your saved charts live in the tab session of the browser you saved them in. Closing that tab or the browser session can discard them, and the favourites will not follow you to a phone, to another browser, or to a colleague on the same instance.

This is a privacy choice with a usability cost, and the project is candid about the alternative. Its future work list includes "save favs encrypted server side?" as an open question, which shows that persistent server side storage was considered and deliberately left undone for now.

The same list also records sharing as partially solved. A proposal to share chords via QR code is marked done, and the README attributes it to an export and import feature added in issue 12. That gives you a manual path to move a favourite between sessions: export it and import it elsewhere. It is a workaround for the session storage limit rather than a replacement for accounts, and the README is careful to mark QR display as still open work.

## Public instances, self hosting, and the FREETAR_LOCAL escape hatch

freetar is usable without touching a server of your own. Three public instances are listed: freetar.de, freetar.habedieeh.re and tabs.adast.dk. They exist so that anyone can look up a chord without installing Python, and they are also the reason a self hosted copy needs a decision about where its data comes from.

Out of the box, a self hosted instance routes its upstream requests through the public Freetar proxies rather than contacting Ultimate Guitar directly. The `FREETAR_LOCAL=1` environment variable changes that: it makes the instance fetch directly from Ultimate Guitar instead. The setting matters for privacy, because the direct mode means your requests go to the upstream site from your own address rather than through a proxy operator, and it matters for reliability, because the proxies are volunteer infrastructure and their availability is not something the project controls.

That leaves three deployment shapes with different trade-offs. Use a public instance and you get no setup and no ownership, and you are trusting whoever runs it. Self host with the default proxy routing and you get control of your own instance but still depend on someone else's proxy for upstream data. Self host with `FREETAR_LOCAL=1` and the dependency shifts to your own network's ability to reach Ultimate Guitar. A fourth option, running only a local copy for your own use, sits at the same address in the compose example and is bound to 127.0.0.1 for exactly that reason.

## Where freetar is the wrong tool

Several cases sit outside what this project can do. Offline practice is the clearest one. The application is a live proxy over a remote site, and while a disk cache can hold pages you have already fetched, the documented cache lives in /tmp by default, which is a volatile location on most systems and is not a curated offline library.

A second limitation is that freetar shows what Ultimate Guitar serves. It is a frontend for one site, not an archive of guitar tabs. Anything the upstream site does not expose to its own pages is not reachable through freetar either, and the project does not claim otherwise. A guitarist who needs a specific older arrangement will have the same luck or lack of it that a direct visitor has.

Third, the browser extension route is no longer part of this project. The README marks the Invidious Redirection style browser extension as done elsewhere, with a link to an issue in the libredirect browser extension repository. If you were expecting freetar to ship its own extension for redirecting Ultimate Guitar links, that expectation no longer matches the project.

Fourth, the invitation to contribute comes with a constraint that is easy to miss. The author asks that people open an issue with a proposal first, and says explicitly that freetar should not become bloated in interface or functionality. Contributors should expect their feature to be argued about against that stated goal rather than merged on request.

## Version 0.21.0, no tagged releases, and a GPL-3.0 codebase

The project version declared in pyproject.toml is 0.21.0, and the README notes that the repository has no GitHub releases, so there is no tag history to compare against and no changelog to skim before an upgrade. Upgrade planning therefore depends on the version number in the packaging metadata and on the commits themselves rather than on release notes. The documentation does not describe a rollback procedure or a documented migration path between versions.

The licence is GPL-3.0, and the Docker image carries the matching `org.opencontainers.image.licenses` label as GPL-3.0-only. Running the software as a service for yourself is a different situation from distributing a modified version, and the obligations differ accordingly. Whether a specific deployment triggers source disclosure obligations is a legal question rather than a technical one, and it is worth reading the licence text rather than relying on a summary.

On maintenance, the repository is not archived and the last push was on 2026-09-25, which is recent relative to the project state described here. The package requires Python 3.9 or newer, and the Dockerfile builds on a Python 3.14 Alpine base, so the container path runs a considerably newer interpreter than the declared floor. The dependency list is small and mainstream, which keeps the cost of a version bump low, but the absence of tagged releases means you should pin the image tag you run rather than tracking `latest` blindly.

## Conclusion

freetar is worth running for anyone who reads tabs regularly and dislikes the upstream interface, or for a group that wants to share one cached copy across a LAN. It is the wrong choice for offline practice, for anyone who needs tab archives that Ultimate Guitar itself does not serve, and for users who need their favourites to persist across devices, since they are held in session storage only. Before adopting it, verify that the configured instance can reach Ultimate Guitar from your network, confirm the caching mode suits your traffic, and read the GPL-3.0 terms if you plan to modify and serve the code yourself.

## FAQ

### How do I install freetar for Ultimate Guitar tabs?

The project is published on PyPI and installs with `pip install freetar`, which puts a `freetar` executable on your PATH. A Docker image is also published under kmille2/freetar and can be run with `sudo docker run -p 127.0.0.1:22000:22000 kmille2/freetar`.

### Which port does freetar listen on and can I change it?

Running the `freetar` executable with no arguments makes it listen on 0.0.0.0:22000. The host and port can be changed with the `FREETAR_HOST` and `FREETAR_PORT` environment variables.

### Do my saved chords in freetar sync to the server?

No. Favourites are stored in session storage and the README states they are not sent to the server, so there is no account and no server side copy of your saved charts.

### How does freetar reduce requests to Ultimate Guitar?

Caching is controlled by `FREETAR_CACHING`, which accepts `ram` (the default, in memory), `disk`, and `off` for development. `FREETAR_CACHE_TIMEOUT` sets how long tabs are kept, with a default of 0 meaning no expiry, and `FREETAR_CACHE_DIR` sets the disk cache location and defaults to /tmp.

### Can freetar fetch tabs directly instead of through the public instances?

Yes. Setting `FREETAR_LOCAL=1` makes the instance fetch directly from Ultimate Guitar rather than routing requests through the public Freetar proxies.

### Is freetar still maintained and does it have release notes?

The repository is not archived and the last push was on 2026-09-25. It has no GitHub releases, so there are no tagged changelogs, and the README does not document a rollback procedure.

## Sources

- [Issues](https://github.com/kmille/freetar/issues)
- [kmille/freetar on GitHub](https://github.com/kmille/freetar)
- [License: GPL-3.0](https://github.com/kmille/freetar/blob/main/LICENSE)
- [README](https://github.com/kmille/freetar/blob/main/README.md)

---

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