Open protocol · v0.1.0 draft
Take your podcast
listening history with you.
PortCast is a small, open JSON protocol for exporting and importing a listener’s podcast subscriptions, play state, queue, bookmarks, and preferences — so changing apps doesn’t mean starting over.
Created by Trimplayer. Free for anyone to implement.
One file. Everything that matters.
Subscriptions
Feeds with tags, identifiers, follow dates — identified by <podcast:guid> when available.
Episode state
unplayed · in_progress · completed · archived, plus position, play count, ratings, stars.
Playback events
Optional event log — play, pause, seek, speed change — so apps can reconstruct how an episode was actually consumed.
Queue
Ordered “up next” that survives switching apps.
Bookmarks & clips
Time-stamped notes inside an episode. Promote to a clip with an end timestamp.
Preferences
Global and per-feed: playback rate, skip intro/outro, trim silence, auto-download policy.
Why a new protocol?
OPML rescues your subscriptions, and nothing else. Per-app exports (Apple, Spotify, Pocket Casts) ship in different, mostly-private shapes. There is no neutral, listener-owned format for the rest of the relationship a listener builds with their podcasts.
PortCast aims to be:
- Vendor-neutral. No central server, no required account. The user owns the file.
- Identity-correct. Matches podcasts by the
podcast:guid
standard, with
feedUrlfallback. Matches episodes by RSS item<guid>, withenclosureUrlfallback. - Lossless within scope, extensible outside it.
Anything outside the spec lives under a reverse-DNS-keyed
extensionsblock that every consumer must preserve. - Tiny. One JSON file. One schema. No required dependency on any podcast directory.
{
"portcast": "0.1.0",
"generatedAt": "2026-05-26T14:00:00Z",
"generator": { "name": "Trimplayer", "version": "3.4.1" },
"subscriptions": [
{
"subscriptionId": "01HXYZ...",
"feedUrl": "https://feeds.example.com/pl.xml",
"podcastGuid": "917393e3-1b1e-5cef-ace4-edaa54e1f810",
"title": "Portable Listening Weekly",
"tags": ["tech"],
"updatedAt": "2026-05-26T14:00:00Z"
}
],
"episodes": [
{
"subscriptionRef": { "podcastGuid": "917393e3-..." },
"guid": "https://feeds.example.com/pl/ep/42",
"status": "in_progress",
"positionSeconds": 1245.2,
"lastPlayedAt": "2026-05-25T08:11:00Z",
"updatedAt": "2026-05-25T08:11:00Z"
}
]
}
Spec & schema
The protocol is defined in SPECIFICATION.md and machine-validated by a JSON Schema (draft 2020-12). A realistic sample document ships in the repo. The spec is published under CC BY 4.0; the reference code under MIT.
Implement it
A Python reference implementation lives in
reference/:
dataclass models, schema-driven validator, OPML ↔ PortCast bridge, and a CLI.
git clone https://github.com/Trim-Player/PortCast.git
cd PortCast/reference
pip install -e ".[dev]"
portcast validate ../examples/sample-export.portcast.json
portcast opml-to-portcast my-subs.opml -o my.portcast.json
portcast inspect my.portcast.json
Building an importer or exporter for another podcast app, or an implementation in another language? Open an issue — we’d like to link your work here.