A Cloudflare Worker that backs up your Pocket Casts data to a D1 database. Runs on an hourly cron with a web UI to browse everything.
- Episodes — your full listen history, including play progress, duration, and starred status
- Podcasts — all your subscriptions with metadata. Unsubscribed podcasts are kept with a removal date rather than deleted.
- Bookmarks — all your bookmarks with timestamps. Deleted bookmarks are kept with a removal date rather than deleted.
Everything is stored in Cloudflare D1 and synced automatically every hour.
- Web UI with episodes, podcasts, and bookmarks pages
- Pagination on the episodes page
- CSV export of your full episode history
- Manual backup trigger via the UI or
/backup
- A Cloudflare account
- Node.js 18+
- A Pocket Casts account
- Clone the repo and install dependencies:
git clone https://github.com/scottrobertson/castkeeper.git
cd castkeeper
npm install- Log in to Cloudflare:
npx wrangler login- Create a D1 database:
npx wrangler d1 create castkeeper- Copy the example wrangler config and add your database ID from the previous step:
cp wrangler.toml.example wrangler.tomlUpdate the database_id in wrangler.toml with the ID output from step 3.
- Set your Pocket Casts credentials as secrets:
npx wrangler secret put EMAIL
npx wrangler secret put PASS- Create the queue:
npx wrangler queues create castkeeper- Apply the database migrations and deploy:
npx wrangler d1 migrations apply castkeeper --remote
npm run deployBackups are split across a Cloudflare Queue so each podcast gets its own Worker invocation, avoiding the subrequest limit. Triggering a backup enqueues one message per podcast, and once all podcasts are synced, a final message fetches your listen history timestamps.
The Pocket Casts API only returns the most recent 100 episodes per request. The worker runs hourly to make sure new listens are captured before they fall outside that window. Each run upserts episodes into D1, so duplicates are handled automatically and your history grows over time.
It also fetches your current podcast subscriptions and bookmarks on each run. If you unsubscribe from a podcast or delete a bookmark, it stays in the database with a deleted_at timestamp rather than being removed. If you re-subscribe or re-add later, the timestamp is cleared. This gives you a full record of what you've been subscribed to and bookmarked over time.
| Path | Description |
|---|---|
/ |
Login page |
/episodes |
Browse your episodes with pagination |
/podcasts |
View your podcast subscriptions |
/bookmarks |
View your bookmarks |
/export |
Download your full episode history as CSV |
/backup |
Triggers a backup manually |
All endpoints are protected by cookie-based authentication using your Pocket Casts password.
Schema changes are managed with D1 migrations in the migrations/ directory.
To create a new migration:
npx wrangler d1 migrations create <migration-name>To apply migrations:
# Local
npx wrangler d1 migrations apply castkeeper --local
# Production
npx wrangler d1 migrations apply castkeeper --remoteCopy the example config and create a .dev.vars file with your credentials:
cp wrangler.toml.example wrangler.toml
cp .env.example .dev.varsEdit .dev.vars with your Pocket Casts email and password, then start the dev server:
npm run dev