Pagination that doesn't lie
Nexarr walks each indexer to exhaustion instead of stopping at the first short page. A missing result is a bug, not a shrug.
correct-pagination Newznab meta-search ● one Go binary
Nexarr fans every search out to all your Newznab indexers, merges the results and strips the duplicates — so Sonarr and Radarr point at one URL instead of a dozen.
SQLite with zero dependencies, or your existing Postgres. No JVM, no runtime.
The problem
You never see what's missing. The same release shows up five times under five slightly different names. And a flaky indexer keeps burning your API quota with nothing to show for it. Nexarr treats correct pagination and fuzzy deduplication as the product — not as details.
What it does
Nexarr walks each indexer to exhaustion instead of stopping at the first short page. A missing result is a bug, not a shrug.
correct-pagination The same release from five indexers, under five names, collapses into one. Spanish and Latin-American dialects are treated as distinct — because they are.
dedup Nexarr counts what you spend using the indexer's own reported apilimits — the figure that already includes what your other clients spent. Failing indexers back off and get disabled.
quota + backoff Go. SQLite with no external dependency, or your existing Postgres — same image, only the driver changes. A one-line docker compose up.
go · sqlite · postgres Sonarr, Radarr and any other client point at one URL. Capabilities are served without a key, so the *arr Test button just works.
t=caps · t=search No enabled indexer, an unreachable database, an unparsable log level — each prints what's wrong and exits non-zero, instead of coming up half-working.
/status How it works
One binary, or one container. SQLite means no external dependency to stand up first.
cp .env.example .env # NEXARR_API_KEY is required
cp config.example.yaml config.yaml
docker compose up -d # SQLite, one service The config file is committable — every secret is an ${ENV} reference. A missing key fails startup instead of silently expanding to empty.
indexers:
- name: example
url: https://indexer.example
api_key: ${EXAMPLE_API_KEY}
enabled: true Add one Newznab indexer with your Nexarr key. One search now fans out to all of them, merged and deduplicated.
# Newznab URL
http://host:5076/api
curl "http://localhost:5076/api?t=caps" Benchmark ● seed 20260731
Three aggregators, four simulated indexers, 30 repetitions per query, on a corpus whose ground truth is exact by construction. The harness is in the repository, so the numbers below are checkable rather than merely stated — including the ones that do not favour us.
99.5%
Recall
NZBHydra2 95.8% on the same corpus
21.1%
Duplicate rate
50.6% fewer repeated rows than NZBHydra2's 42.6%
3.3 MB
Idle memory
209× less than NZBHydra2's 689 MB
7 ms
Cold start
206× faster to first correct answer
Where it is a draw: at realistic indexer latency our p95 is 232 ms against their 236 ms. That gap is smaller than the drift between two runs of the same build, so it is a tie, and the table below marks it as one.
Where it stands ● v0.1
This is v0.1. It runs the full pipeline in production, and there are things it doesn't do yet. Here's exactly which is which.
Requires Go 1.26+. MIT licensed. No JVM, no runtime, no account — just a binary and your config.
git clone https://github.com/nexarr-app/nexarr.git && cd nexarr && make build