Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Export OPML from Apple Podcasts app on macOS

Export OPML from Apple Podcasts app on macOS (tested on macOS 12 Monterey)

  1. Download following script
  2. Make downloaded file executable $ chmod +x ~/Download/ApplePodcastToOMPL.js
  3. Run $ ~/Downloads/ApplePodcastToOMPL.js to see the OPML output
  4. If it looks okay, $ ~/Downloads/ApplePodcastToOMPL.js > ~/Downloads/ApplePodcasts.opml

If default sqlite path not working for you, you can specify a custom one $ ~/Downloads/ApplePodcastToOMPL.js /my/custom/MTLibrary.sqlite

#!/usr/bin/env node
const { exit } = require('process');
const PREDEFINED_PATH = "~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Documents/MTLibrary.sqlite";
const XML_TEMPLATE = `<?xml version="1.0"?>
<!-- example OPML file -->
<opml version="1.0">
<head>
<title>Overcast Podcast Subscriptions</title>
</head>
<body>
%BODY%
</body>
</opml>`;
const XML_PODCAST_TEMPLATE = `<outline type="rss" title="%TITLE%" text="%TEXT%" xmlUrl="%RSS_URL%" htmlUrl="%WEB_URL%"/>`;
const escapeString = (str) => {
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
};
const args = process.argv.slice(2);
const sqlitePath = (args.length >= 1 ? args[0] : PREDEFINED_PATH).replace(/ /g, '\\ ');
console.log(`sqlitePath: "${sqlitePath}"`);
let jsonOutputString;
try {
jsonOutputString = require('child_process').execSync(`sqlite3 ${sqlitePath} "SELECT ZTITLE,ZITEMDESCRIPTION,ZFEEDURL,ZWEBPAGEURL FROM ZMTPODCAST WHERE ZSUBSCRIBED = 1" -json`).toString();
} catch (error) {
console.error(`Failed to parse sqlite file: ${sqlitePath}`);
exit(-1);
}
const jsonOutput = JSON.parse(jsonOutputString);
const bodyArray = jsonOutput.map((podcast) => XML_PODCAST_TEMPLATE
.replace('%TITLE%', escapeString(podcast['ZTITLE']))
.replace('%TEXT%', escapeString(podcast['ZITEMDESCRIPTION']))
.replace('%RSS_URL%', podcast['ZFEEDURL'])
.replace('%WEB_URL%', podcast['ZWEBPAGEURL']));
const output = XML_TEMPLATE.replace('%BODY%', bodyArray.join('\n'));
console.log(output);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment