Skip to content

joemc1470/pageturnarr

Pageturnarr

build license version

Self-hosted book and audiobook automation — a working replacement for Readarr.

Why this exists

Readarr is officially retired: the Servarr team shut it down after its metadata source, Goodreads, locked down its public API, and nobody stepped up to migrate it to a workable alternative. If you were running Readarr, you're currently stuck on an unmaintained tool with a broken metadata backend.

Pageturnarr is a from-scratch replacement built around two decisions that avoid Readarr's failure mode:

  • Metadata from OpenLibrary and Google Books, not Goodreads — no dependency on an API that can be revoked by a third party.
  • Ebooks and audiobooks in one instance, not two separate Readarr/ Readarr-audio setups.

It also adds Send-to-Kindle (convert + email a successful ebook import straight to a registered Kindle address), which Readarr never had.

Pageturnarr is pre-release software (v0.1.0). It has a tested backend and a working frontend, and the maintainer runs it against real indexers and a real SABnzbd instance — but it hasn't had a broad multi-user shakeout yet. Expect rough edges. See what it doesn't do yet before you commit your library to it.

What it does

Pageturnarr automates the same acquisition loop as Sonarr/Radarr, applied to books and audiobooks:

metadata search → indexer search → score → grab → download → post-process → organize → notify

  • Metadata search & monitoring against OpenLibrary and Google Books, for both books and audiobooks.
  • Indexer search via direct Newznab (NZBgeek, NZBPlanet, or any Newznab-compatible indexer) or through Prowlarr as an aggregator.
  • Release scoring — ranks results by preferred/blocked formats, an acceptable size window, and preferred/blocked keywords in the release title.
  • SABnzbd (Usenet) and qBittorrent (torrent) downloads. Use either client or both in the same instance; PROTOCOL_PREFERENCE decides how results from the two protocols compete. SABnzbd gets offline resilience (a download is queued even if it's briefly unreachable, and retried automatically), and both clients get automatic category routing (books vs. audiobooks). Torrent imports are copied or hardlinked into your library so seeding continues.
  • Download lifecycle tracking — real status transitions (wanted → downloading → imported), progress/speed/ETA, retry of failed grabs, and title-based blocklisting.
  • Post-processing — organizes ebooks by author/title, and tags audiobooks (ID3v2 for MP3, MP4 atoms for M4B/M4A: title, author, series, narrator, cover art) and organizes them by author/series/title. See docs/post-processing.md.
  • Send-to-Kindle — converts and emails successful ebook imports to a Kindle address via SMTP.
  • Quality profiles with per-profile cutoffs and automatic upgrades (re-grab when a better release shows up).
  • Database-backed indexer configuration — indexers are managed through the UI/API and are the single source of truth for search (no more env-only indexer config).
  • Import lists with exclusions, for auto-adding titles from external sources.
  • Calendar view and iCal feed for upcoming releases.
  • Notifications via Discord webhook and/or Obsidian vault notes (one markdown note per import).
  • Unified web UI — Library, Wanted, Add, Activity, Calendar, and Settings, covering both media types from one interface.

As of this release, the backend test suite passes (225 tests) and the frontend production build succeeds. See CHANGELOG.md for the full v0.1.0 feature list.

What it doesn't do yet

Honestly, and in rough order of how often they matter:

  • API-key auth only. All /api/* routes require the X-Api-Key header (Sonarr/Radarr-style; the key is generated on first startup and shown in Settings). There is no multi-user login or 2FA — still treat a public-internet exposure with care (reverse proxy + your own auth layer).
  • No Transmission support. SABnzbd (Usenet), qBittorrent, and Deluge are the supported downloaders; other torrent clients remain on the roadmap (see ROADMAP.md).
  • No tags or per-item configuration. Quality profile, monitored state, and root folder are global/profile-level, not overridable per book or author.
  • No configurable naming/folder templates. Output layout is hardcoded in the post-processing service.
  • Young migration history. Schema changes ship as Alembic migrations and run automatically on startup (with a pre-upgrade SQLite backup — see docs/MIGRATIONS-AND-BACKUP.md). A database that doesn't match any known revision fails startup rather than guessing.
  • No Readarr import. There's no migration tool to pull an existing Readarr library/history into Pageturnarr yet.

Full list with complexity estimates: ROADMAP.md.

Screenshots

Library Activity Add
Library view Activity view Add view

Quickstart

Requires Docker and Docker Compose, an existing SABnzbd instance (Usenet) and/or qBittorrent instance (torrents), plus at least one Newznab-compatible indexer (or a Prowlarr instance aggregating indexers for you).

  1. Clone the repo and copy the example environment file:

    git clone <this-repo-url>
    cd pageturnarr
    cp .env.example .env
  2. Edit .env — configure at least one downloader (SABNZBD_URL and SABNZBD_API_KEY for Usenet, and/or QBITTORRENT_URL with QBITTORRENT_USERNAME/QBITTORRENT_PASSWORD for torrents), plus at least one indexer (NZBGEEK_URL/NZBGEEK_API_KEY, or PROWLARR_URL/ PROWLARR_API_KEY). See Usenet, torrents, or both below to tune which protocol wins.

  3. Start it with the checked-in Compose file (single container — the backend serves the built web UI):

    docker compose up -d

    Or with plain Docker:

    docker build -t pageturnarr .
    docker run -d --name pageturnarr \
      -p 8000:8000 \
      -e PUID=1000 -e PGID=1000 \
      -v pageturnarr_config:/config \
      -v /path/to/library:/books \
      -v /path/to/downloads:/downloads \
      --env-file .env \
      pageturnarr

    See DOCKER.md for the full deployment reference (volumes, PUID/PGID, healthcheck, upgrades).

  4. Open http://<host>:8000 in a browser. On first startup the app generates an API key (shown in the container log and in Settings) — the UI will prompt you for it once.

Auth is API-key only (no multi-user login) — for anything internet-facing, keep a reverse proxy with your own access controls in front.

Usenet, torrents, or both

Pageturnarr supports SABnzbd (Usenet) plus qBittorrent or Deluge (torrents) independently — run any combination in the same instance. When both are configured, PROTOCOL_PREFERENCE decides how results compete:

  • prefer-usenet (default) — Usenet wins ties; torrents fill gaps.
  • prefer-torrent — torrents win ties; Usenet fills gaps.
  • usenet-only — ignore torrent results entirely.
  • torrent-only — ignore Usenet results entirely.

Torrent results come from your Prowlarr/torznab indexers; among otherwise equal releases, more seeders win. Imports from qBittorrent are copied or hardlinked into your library (never moved or deleted), so seeding continues uninterrupted.

Configuration

All configuration is via environment variables (see .env.example and backend/app/config.py). Secrets have no defaults and must be set explicitly.

Variable Default Description
APP_NAME Pageturnarr Display name used in the API title.
DEBUG false Enables debug mode.
LOG_LEVEL INFO Python logging level.
DATABASE_URL sqlite+aiosqlite:///./pageturnarr.db SQLAlchemy async database URL.
BOOKS_ROOT /data/media/ebooks Library root for organized ebooks.
AUDIOBOOKS_ROOT /data/media/audiobooks Library root for organized audiobooks.
ENABLE_POSTPROCESS true Toggles the post-processing pipeline.
CALIBRE_PATH calibredb Path to Calibre's CLI tools, if installed.
SABNZBD_URL http://sabnzbd:8080 SABnzbd base URL.
SABNZBD_API_KEY (none — required) SABnzbd API key.
QBITTORRENT_URL http://qbittorrent:8080 qBittorrent base URL.
QBITTORRENT_USERNAME (none) qBittorrent WebUI username.
QBITTORRENT_PASSWORD (none) qBittorrent WebUI password.
QBITTORRENT_CATEGORY pageturnarr qBittorrent category Pageturnarr assigns to its downloads.
PROTOCOL_PREFERENCE prefer-usenet How Usenet and torrent results compete: prefer-usenet, prefer-torrent, usenet-only, or torrent-only.
DELUGE_URL http://deluge:8112 Deluge WebUI base URL. Setting DELUGE_PASSWORD enables Deluge; when qBittorrent is also configured, qBittorrent takes new grabs.
DELUGE_PASSWORD (none) Deluge WebUI password.
PUID / PGID 1000 / 1000 User/group the app runs as (it refuses to run as root). The entrypoint owns /config and the configured library roots at startup; make sure these match the owner of your media mounts, *arr-style.
PLEX_URL (none) Plex server URL (optional).
PLEX_TOKEN (none) Plex auth token (optional).
AUDIOBOOKSHELF_URL (none) Audiobookshelf URL — when set (with token), triggers a library scan after each audiobook import.
AUDIOBOOKSHELF_TOKEN (none) Audiobookshelf admin API token.
AUTO_DOWNLOAD_WANTED false Auto-grab the top indexer result for wanted+monitored items. Opt-in.
DISCORD_WEBHOOK_URL (none) Discord webhook for import success/failure notifications.
OBSIDIAN_VAULT_PATH (none) Path to an Obsidian vault (must be writable by the container) — Pageturnarr writes one note per import under Pageturnarr/Books or Pageturnarr/Audiobooks.
KINDLE_EMAIL (none) Destination @kindle.com address for Send-to-Kindle.
KINDLE_SEND_ENABLED false Enables Send-to-Kindle on successful ebook import.
KINDLE_FORMAT epub Format emailed to Kindle (epub needs no conversion; azw3 requires calibredb).
SMTP_HOST (none) SMTP server for Send-to-Kindle.
SMTP_PORT 587 SMTP port.
SMTP_USERNAME (none) SMTP username.
SMTP_PASSWORD (none) SMTP password (use an app password for Gmail, etc.).
SMTP_FROM (none) From address — must be on Amazon's approved sender list for the target Kindle.
SMTP_USE_TLS true Use TLS for SMTP.
PREFERRED_BOOK_FORMATS epub,azw3,mobi,pdf Format preference order used by release scoring.
MIN_BOOK_SIZE_KB 100 Minimum acceptable ebook size.
MAX_BOOK_SIZE_KB 100000 Maximum acceptable ebook size.
BLOCKED_RELEASE_WORDS comic,magazine,manga,audiobook,m4b,mp3 Release title tokens that reject a result outright.
PREFERRED_RELEASE_WORDS retail,proper,repack Release title tokens that add a small scoring bonus.
GOOGLE_BOOKS_API_KEY (none) Optional — raises Google Books rate limits.
OPENLIBRARY_BASE_URL https://openlibrary.org OpenLibrary API base URL.
GOOGLE_BOOKS_BASE_URL https://www.googleapis.com/books/v1 Google Books API base URL.
PROWLARR_URL (none) Prowlarr base URL. When set with an API key, search routes through Prowlarr instead of direct Newznab.
PROWLARR_API_KEY (none) Prowlarr API key.
PROWLARR_INCLUDE_TORRENTS false Include torrent results from Prowlarr; grabbed via qBittorrent when configured.
NZBGEEK_URL https://api.nzbgeek.info NZBgeek Newznab endpoint (direct-indexer fallback).
NZBGEEK_API_KEY (none) NZBgeek API key.
NZBPLANET_URL https://api.nzbplanet.net NZBPlanet Newznab endpoint.
NZBPLANET_API_KEY (none) NZBPlanet API key.
SEARCH_INTERVAL_HOURS 6 How often the scheduler searches for wanted/missing items.
IMPORT_INTERVAL_MINUTES 15 How often the scheduler checks for completed downloads to import.
CORS_ORIGINS http://localhost:5173,http://localhost:3000,http://localhost:8000 Allowed CORS origins for the API.

Documentation

License

Pageturnarr is licensed under the GNU General Public License v3.0.

© 2026 Joe McLaughlin

About

Self-hosted ebook & audiobook automation for the *arr crowd — usenet + torrents (SABnzbd/qBittorrent/Deluge), seeding-safe imports, calibre post-processing, Audiobookshelf sync. FastAPI + React, single container.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors