🚀 Executive Summary

TL;DR: This guide addresses the problem of losing Pocket Casts subscriptions due to app glitches by providing a robust, automated backup solution. It details a Python script that authenticates with the Pocket Casts API, fetches user subscriptions, and exports them to a standard OPML file for peace of mind and data integrity.

🎯 Key Takeaways

  • The solution leverages Python with `requests` for API interaction, `python-dotenv` for secure credential management, and `lxml` for OPML file generation.
  • Authentication with the unofficial Pocket Casts API requires an email and password to obtain a bearer token, which is then used to fetch the user’s podcast subscription list.
  • Podcast subscription data, including titles and RSS URLs, is programmatically converted into an OPML 2.0 XML file, ensuring a standardized and portable backup format.
  • Automation via a cron job is recommended to ensure consistent, scheduled backups, making the solution a ‘set-it-and-forget-it’ system for data resilience.

Syncing Pocket Casts subscriptions to OPML for backup

Syncing Pocket Casts subscriptions to OPML for backup

Alright, let’s talk about a small but crucial piece of automation. I listen to a ton of podcasts—everything from SRE deep dives to cybersecurity news. A while back, an app update glitched and wiped out a custom folder with about 20 subscriptions I was vetting for the team. Re-finding all of them was a massive pain. It was one of those “never again” moments. That’s why I built this simple Python script to automatically back up my Pocket Casts subscriptions to a standard OPML file. It’s a set-it-and-forget-it solution that gives me peace of mind.

This isn’t about fancy dashboards; it’s about robust, simple data integrity. Let’s get it done.

Prerequisites

Before we dive in, make sure you have the following ready:

  • Python 3.x installed on your system.
  • Your Pocket Casts login credentials (email and password).
  • Basic comfort with running Python scripts and managing dependencies.

The Guide: Step-by-Step

Step 1: Project Setup

First, you’ll need a directory for our project. I’ll skip the standard virtualenv setup commands since you likely have your own workflow for that. Just make sure you’re working in an isolated environment.

Inside your project directory, you’ll need three things:

  1. A Python script file we’ll call pocketcasts_sync.py.
  2. A configuration file named config.env to securely store our credentials.
  3. The script will generate our backup, subscriptions.opml, in this same directory.

Step 2: Installing Dependencies

We need a few Python libraries to make this work. You’ll want to install requests for making HTTP calls, python-dotenv for managing our credentials from the `config.env` file, and lxml for building the OPML file. You can install these using your standard package manager, for instance, with `pip`.

Step 3: Storing Your Credentials

Let’s get that config.env file set up. This is much safer than hardcoding your credentials directly in the script.

Create the `config.env` file and add your Pocket Casts email and password:

POCKETCASTS_EMAIL="your_email@example.com"
POCKETCASTS_PASSWORD="your_super_secret_password"

Pro Tip: In my production setups, I’d pull these from a proper secrets manager like HashiCorp Vault or AWS Secrets Manager. For a personal script like this, a `config.env` file excluded from version control (via `.gitignore`) is a perfectly reasonable approach.

Step 4: The Python Script

Now for the core logic. Open up pocketcasts_sync.py and let’s build this out. The script will perform four key actions:

  1. Load credentials from our `config.env` file.
  2. Authenticate with the Pocket Casts API to get a token.
  3. Fetch the list of your current podcast subscriptions.
  4. Generate an OPML file from that list.

Here is the complete script. I’ve added comments to explain what each part does.

import os
import requests
from dotenv import load_dotenv
from lxml import etree

def authenticate(email, password):
    """Authenticates with Pocket Casts and returns an auth token."""
    auth_url = 'https://api.pocketcasts.com/user/login'
    payload = {'email': email, 'password': password, 'scope': 'web'}
    try:
        response = requests.post(auth_url, json=payload)
        response.raise_for_status()  # This will raise an HTTPError for bad responses (4xx or 5xx)
        token = response.json().get('token')
        if not token:
            print("Authentication failed. Token not found in response.")
            return None
        print("Successfully authenticated with Pocket Casts.")
        return token
    except requests.exceptions.RequestException as e:
        print(f"Error during authentication: {e}")
        return None

def fetch_subscriptions(token):
    """Fetches the user's podcast subscriptions."""
    subs_url = 'https://api.pocketcasts.com/user/podcast/list'
    headers = {'Authorization': f'Bearer {token}'}
    try:
        response = requests.post(subs_url, headers=headers)
        response.raise_for_status()
        podcasts = response.json().get('podcasts')
        if podcasts is None:
            print("Could not find 'podcasts' key in the subscription response.")
            return []
        print(f"Found {len(podcasts)} podcast subscriptions.")
        return podcasts
    except requests.exceptions.RequestException as e:
        print(f"Error fetching subscriptions: {e}")
        return []

def generate_opml(podcasts, output_file):
    """Generates an OPML file from a list of podcasts."""
    opml = etree.Element('opml', version='2.0')
    head = etree.SubElement(opml, 'head')
    title = etree.SubElement(head, 'title')
    title.text = "Pocket Casts Subscriptions"
    body = etree.SubElement(opml, 'body')

    for podcast in podcasts:
        etree.SubElement(body, 'outline',
                         type='rss',
                         text=podcast.get('title', 'No Title'),
                         xmlUrl=podcast.get('url', ''))

    # Use lxml's tostring method to get a nicely formatted XML string
    opml_string = etree.tostring(opml, pretty_print=True, xml_declaration=True, encoding='UTF-8')

    try:
        with open(output_file, 'wb') as f: # Write in binary mode
            f.write(opml_string)
        print(f"Successfully saved subscriptions to {output_file}")
    except IOError as e:
        print(f"Error writing to file {output_file}: {e}")

def main():
    """Main function to run the sync process."""
    load_dotenv('config.env')
    email = os.getenv('POCKETCASTS_EMAIL')
    password = os.getenv('POCKETCASTS_PASSWORD')
    output_filename = 'subscriptions.opml'

    if not email or not password:
        print("Error: POCKETCASTS_EMAIL or POCKETCASTS_PASSWORD not set in config.env")
        return

    auth_token = authenticate(email, password)
    if auth_token:
        podcast_list = fetch_subscriptions(auth_token)
        if podcast_list:
            generate_opml(podcast_list, output_filename)
        else:
            print("No podcasts to process. OPML file not generated.")
    else:
        print("Could not proceed without authentication token.")


if __name__ == "__main__":
    main()

Step 5: Automation

A backup script is only useful if it runs consistently. I use a simple cron job for this. Set it to run weekly, and you’ll always have a recent backup.

Here’s an example cron entry that runs the script every Monday at 2:00 AM.
`0 2 * * 1 python3 script.py`

Pro Tip: Make sure your cron job runs in the context of your project directory or use absolute paths for the script and the output file in your Python code. I prefer the former to keep the script portable. Also, direct the output of your cron job to a log file (`>> /path/to/your/logs/pocketcasts.log 2>&1`) to capture any errors.

Common Pitfalls

Here is where I usually mess up on the first try:

  • API Changes: The Pocket Casts API is not officially public, so it can change without notice. If the script suddenly stops working, the first thing I check is if the API endpoints or the authentication payload have been updated.
  • Credential Errors: A simple typo in the config.env file can lead to authentication failures. Double-check that your email and password are correct and that the script has permission to read the file.
  • File Permissions: The most classic problem. The script needs write permissions in the directory where it’s running to create the subscriptions.opml file. If you see an `IOError`, this is the likely culprit.

Conclusion

And that’s it. With a simple Python script and a cron job, you’ve built a resilient, automated backup system for your podcast library. This is a small investment of time that saves you from a massive headache down the road. It embodies a core DevOps principle: automate the boring stuff so you can focus on what matters. Now you can be sure your carefully curated list of subscriptions is safe and sound.

Darian Vance - Lead Cloud Architect

Darian Vance

Lead Cloud Architect & DevOps Strategist

With over 12 years in system architecture and automation, Darian specializes in simplifying complex cloud infrastructures. An advocate for open-source solutions, he founded TechResolve to provide engineers with actionable, battle-tested troubleshooting guides and robust software alternatives.


🤖 Frequently Asked Questions

âť“ How can I automatically back up my Pocket Casts subscriptions to an OPML file?

You can use a Python script that authenticates with the Pocket Casts API using your credentials, fetches your list of subscribed podcasts, and then generates an OPML 2.0 formatted XML file containing the podcast details.

âť“ Are there official Pocket Casts features for exporting subscriptions, or how does this script compare to alternatives?

The article implies the Pocket Casts API is not officially public, suggesting this script is a custom, community-driven solution for a missing official export feature. It prioritizes robust, simple data integrity over fancy dashboards, providing a direct OPML backup.

âť“ What are common pitfalls when implementing this Pocket Casts subscription backup script?

Common pitfalls include unannounced Pocket Casts API changes that can break the script, credential errors in the `config.env` file leading to authentication failures, and file permission issues preventing the script from writing the `subscriptions.opml` file.

Leave a Reply

Discover more from TechResolve - SaaS Troubleshooting & Software Alternatives

Subscribe now to keep reading and get access to the full archive.

Continue reading