An unofficial AltStore-format source collection for Stremio iOS and tvOS, compatible with any signing app that consumes the standard AltStore source format — Feather, AltStore Classic, AltStore PAL, ESign, Scarlet, Sideloadly, and others. Stremio's official source at dl.strem.io/apple/altstore/source.json cannot be parsed by most third-party signing apps because it uses Apple's encrypted App Store Connect manifest format — this repo publishes standard AltStore-format JSON sources that point to Stremio's plain IPA artifacts.
- Why does this repo exist?
- Compatible signing apps
- Quick start
- Self-host your own copy
- Available versions
- Automatic updates
- Manual updates
- Architecture
- Limitations
- Contributing
- License and attribution
Starting in June 2026, Stremio moved iOS distribution entirely to Apple's App Store Connect marketplace format. This format:
- Packages IPAs as encrypted variant chunks
- Distributes a
manifest.jsonmetadata file - Grants the decryption key only to AltStore PAL
Most third-party signing apps (Feather, ESign, Scarlet, Sideloadly, etc.) cannot break this encryption, so importing the official source results in "no apps", "invalid format", or "failed to download" errors.
However, Stremio keeps the plain IPA files publicly available on the same CDN:
https://dl.strem.io/apple/{X.Y.Z}b{buildN}/{ios|tvos}/stremio_{Platform}.ipa
This repo discovers those IPAs and writes them into standard AltStore-format JSON sources.
📜 Related discussions:
Any signing app that consumes the standard AltStore source format can use this repo. Tested or known-compatible apps include:
- Feather — open-source on-device signer
- AltStore Classic — the original desktop-paired signer (requires AltServer on a Mac/PC)
- AltStore PAL — AltStore's European Union alternative marketplace
- ESign — popular on-device signer
- Scarlet — on-device IPA installer
- Sideloadly — desktop-based sideloader with source support
If your signing app supports adding a source by URL pointing to an apps.json-style document, it will work. If you find an app that does not work, please open an issue.
No fork required. This source is already hosted and auto-updated every 6 hours. Just add it to your signing app.
Open this page on your iPhone / iPad and tap your app — the source opens prefilled:
Direct deep links (tap on-device, or paste into Safari):
| Platform | AltStore | SideStore |
|---|---|---|
| iOS / iPadOS | Open in AltStore | Open in SideStore |
| tvOS | Open in AltStore | Open in SideStore |
GitHub strips
altstore://-style links in this README, so the table links only work once pasted into Safari. The Add to AltStore / SideStore button above routes through a landing page and works directly.
Works with any signing app (Feather, AltStore Classic/PAL, ESign, Scarlet, Sideloadly…). Paste the URL into the app's Sources / Repositories section:
| Platform | Source URL |
|---|---|
| iOS / iPadOS | https://gorlev.github.io/stremio-altstore/stremio-ios.json |
| tvOS | https://gorlev.github.io/stremio-altstore/stremio-tvos.json |
Once added, Stremio appears in the app's source list. Pick a version and tap Get (or the equivalent) to download and sign.
sourceURL also works with raw.githubusercontent.com:
https://raw.githubusercontent.com/gorlev/stremio-altstore/main/stremio-ios.json
https://raw.githubusercontent.com/gorlev/stremio-altstore/main/stremio-tvos.json
Some signing apps require the Content-Type: application/json header, which GitHub Pages guarantees; raw URLs occasionally delay that header — prefer the gorlev.github.io URLs above.
Prefer to run your own source (own URL, own update schedule)? Fork and host it in a couple of minutes:
- Fork this repository.
- Enable Pages: Settings → Pages → Source: Deploy from a branch → Branch:
main/(root). After a few minutes your sources are live athttps://<your-github-username>.github.io/stremio-altstore/stremio-{ios,tvos}.json. - Point
sourceURLat your fork:python3 stremio-updater.py \ --source-url-ios "https://<your-github-username>.github.io/stremio-altstore/stremio-ios.json" \ --source-url-tvos "https://<your-github-username>.github.io/stremio-altstore/stremio-tvos.json"
- Commit the change. The included GitHub Actions workflow keeps your fork updated every 6 hours.
| Version | Build | Date | Size | Download |
|---|---|---|---|---|
| 2.0.8 | 23 | 2026-09-10 | 74.9 MB | IPA |
| 2.0.7 | 22 | 2026-08-24 | 75.1 MB | IPA |
| 2.0.6 | 21 | 2026-07-22 | 72.4 MB | IPA |
| 2.0.5 | 20 | 2026-07-22 | 72.7 MB | IPA |
| 2.0.4 | 19 | 2026-07-10 | 72.7 MB | IPA |
| 2.0.3 | 18 | 2026-07-09 | 72.7 MB | IPA |
| 2.0.2 | 17 | 2026-06-19 | 74.4 MB | IPA |
| 2.0.1 | 16 | 2026-06-16 | 74.1 MB | IPA |
| 2.0.1 | 15 | 2026-06-15 | 74.1 MB | IPA |
| 2.0.0 | 14 | 2026-06-05 | 74.4 MB | IPA |
| 2.0.0 | 13 | 2026-06-05 | 74.1 MB | IPA |
| 2.0.0 | 11 | 2026-05-30 | 74.4 MB | IPA |
| Version | Build | Date | Size | Download |
|---|---|---|---|---|
| 2.0.8 | 23 | 2026-09-10 | 70.6 MB | IPA |
| 2.0.7 | 22 | 2026-08-24 | 70.6 MB | IPA |
| 2.0.6 | 21 | 2026-07-22 | 70.6 MB | IPA |
| 2.0.5 | 20 | 2026-07-22 | 70.6 MB | IPA |
| 2.0.3 | 18 | 2026-07-09 | 70.6 MB | IPA |
| 2.0.2 | 17 | 2026-06-19 | 70.2 MB | IPA |
| 2.0.1 | 16 | 2026-06-16 | 70.2 MB | IPA |
| 2.0.1 | 15 | 2026-06-15 | 70.2 MB | IPA |
🤖 The tables above are auto-generated from the JSON sources by
scripts/render_readme.pyon every update — do not edit them by hand.
📦 Every version was verified against the IPA's Info.plist (downloaded via HTTP Range, < 5 KB each). Bundle identifiers, version strings, and
MinimumOSVersionvalues were read directly from the IPAs.
The repo includes a GitHub Actions workflow that runs stremio-updater.py every 6 hours, discovers new Stremio versions, updates the JSON files, and auto-commits. With GitHub Pages enabled, new versions appear in your signing app within minutes.
Every run starts by executing the test suite (python3 -m unittest discover -s scripts -p 'test_*.py', under a second and no network). It covers the parts whose failure would be silent rather than loud: the ZIP/plist parser that reads minOSVersion out of a remote IPA, the safety rails on the one script that deletes versions, the version-discovery logic that once missed a release for five straight runs, and the publish gate itself.
Nothing is ever pushed without passing scripts/validate_source.py first. Five different scripts write to these JSON files, and whatever lands here reaches users within minutes, so the gate checks more than "is this JSON": every downloadURL must be https on Stremio's own CDN (a sideloading source must never send people elsewhere for an unsigned IPA), bundle identifiers must be unique within a source, sourceURL must name its own file, no app may be published with zero versions, and sizes, dates and sha256 values must be plausible. If it fails, the job fails and nothing is published. scripts/test_validate_source.py corrupts a known-good source one way at a time to prove the gate still fires.
Each run also, in the same job:
- Captures release notes —
scripts/fetch_release_notes.pycopies each build's real changelog from Stremio's own AltStore source (its download URLs are the marketplace format this repo works around, but its release notes are usable). That source only carries the newest couple of builds, so this has to run on the same cadence to catch each changelog before it rolls out of their window — and it never drops one it has already captured. Builds released before this existed keep their generated placeholder, except where an Internet Archive capture of that same upstream URL still holds the changelog — the weekly audit mines those to fill gaps, and never overwrites a note already captured. - Mirrors the newest build into the legacy app-level fields — the AltStore format has two generations: modern clients read each app's
versionsarray, while AltStore Classic and several forks read flatversion/versionDescription/downloadURLfields on the app itself.scripts/sync_legacy_fields.pykeeps both in step, so older clients show the real changelog instead of falling back to something like "Stremio 2.0.6 build 21". The publish gate rejects a mirror that disagrees with the newest version, since old and new clients installing different builds from one entry would be worse than shipping no legacy fields at all. - Proves it is still running — the install page asks GitHub when this workflow last succeeded and shows it ("Checked 2 hours ago"). The badge's green dot is therefore earned rather than decorative: if the automation stalls, it turns amber and then red instead of reassuring people about a source nobody is maintaining.
- Rebuilds the in-app news feed — signing apps render a source's
newsarray inside the app, soscripts/build_news.pyturns each captured changelog into an item that links back to the app entry. Only the newest release may request a push notification, and only while it is genuinely fresh, so publishing or rebuilding the feed never fires a burst of notifications; identifiers are derived from the release alone so a client notifies at most once. The publish gate enforces both. - Backfills integrity hashes —
scripts/add_hashes.pycomputes thesha256of a few IPAs per run (newest first, budget-limited so it never risks the job's time limit), so every version eventually carries a hash that signing apps can verify the download against. - Regenerates the version tables in this README from the JSON.
The updater only ever looks for new builds, so a second workflow (.github/workflows/audit.yml) runs weekly to catch what that misses:
- Dead downloads —
scripts/prune_dead.pyHEAD-checks every listed IPA. When Stremio pulls an old build, the entry is removed so nobody is left tapping a link that 404s. It is deliberately cautious: only 404/410 counts (never a timeout or 5xx), each one is re-checked, and it prunes nothing at all if the newest version is missing or if many die at once — those look like a CDN change, not individual pulls. Dropping an app that has no working versions left is left to a human. - Retention —
scripts/trim_versions.pystops the version list growing without bound. It keeps the newest dozen builds, and additionally never drops a build that is the last option for a givenminOSVersionor the last of a release line — so a device stuck on an older OS cannot be stranded by housekeeping. On today's list nothing is trimmed; the policy matters as the list grows. - Screenshots —
scripts/fetch_screenshots.pycopies the real App Store screenshots from Stremio's own source, so entries show a gallery instead of a bare name and icon. Upstream only publishes iPhone and iPad shots, so the tvOS source is deliberately left without any rather than showing phone screenshots for a TV app. - Metadata drift —
scripts/verify_bundle_ids.pyreads each IPA's realInfo.plistand compares the bundle identifier, version, build andMinimumOSVersionagainst what the JSON claims. It correctsminOSVersionin place (the IPA is the authority, and the field only advertises compatibility); a mismatched bundle identifier, version or build defines the entry's identity, so those are reported for a human instead.
Anything needing a decision opens a single deduplicated GitHub issue.
A separate CDN health canary (scripts/check_cdn.py) runs on the 6-hour schedule. Because the updater exits successfully whether it finds new versions or finds nothing, a broken CDN (a changed URL scheme, an outage, or a pulled build) would otherwise be invisible. The canary HEAD-checks the newest known IPA for each platform and opens a GitHub issue (deduplicated — one at a time) if the source may be serving dead downloads.
To enable the workflow: Actions → Update Stremio source → Enable workflow.
To trigger manually: Actions → Update Stremio source → Run workflow.
Configuration lives in .github/workflows/update.yml.
# Clone the repo
git clone https://github.com/gorlev/stremio-altstore.git
cd stremio-altstore
# Virtual environment (optional but recommended)
python3 -m venv .venv && source .venv/bin/activate
# Dry run — see what would change without writing files
python3 stremio-updater.py --dry-run --verbose
# Real update — write changes to JSON files
python3 stremio-updater.py
# Parse Info.plist for unknown IPAs to verify bundle IDs (slower)
python3 stremio-updater.py --info-plist
# Only iOS (or only tvOS)
python3 stremio-updater.py --platform ios
python3 stremio-updater.py --platform tvos
# Update sourceURL fields
python3 stremio-updater.py \
--source-url-ios "https://<your-github-username>.github.io/stremio-altstore/stremio-ios.json" \
--source-url-tvos "https://<your-github-username>.github.io/stremio-altstore/stremio-tvos.json"
# Commit and push
git add stremio-ios.json stremio-tvos.json
git commit -m "chore: update Stremio source"
git pushShorter aliases via make:
make help # List all targets
make dry-run # Dry run
make update # Real update
make verify # Update with Info.plist verification
make set-urls # Set sourceURL fields interactivelystremio-altstore/
├── README.md ← this file
├── LICENSE ← MIT
├── CHANGELOG.md ← version history
├── CONTRIBUTING.md ← contribution guide
├── SECURITY.md ← security policy
├── Makefile ← shortcut commands
├── .gitignore ← Python / macOS / IDE
├── stremio-ios.json ← main source (iOS / iPadOS)
├── stremio-tvos.json ← main source (tvOS)
├── stremio-updater.py ← CDN scanner + JSON updater
├── ipa_plist.py ← shared HTTP-Range IPA Info.plist parser
├── install.html ← one-tap install landing page (GitHub Pages)
├── .github/
│ ├── dependabot.yml ← keeps the workflow actions current
│ ├── workflows/
│ │ ├── update.yml ← auto-update every 6 hours + CDN canary
│ │ └── audit.yml ← weekly dead-IPA prune + metadata verify
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.yml
│ ├── feature_request.yml
│ └── source_broken.yml
└── scripts/
├── verify_bundle_ids.py ← standalone IPA Info.plist verifier
├── render_readme.py ← regenerates the version tables above
├── add_hashes.py ← backfills sha256 integrity hashes (budgeted)
├── check_cdn.py ← CDN health canary (opens an issue if broken)
├── prune_dead.py ← removes versions whose IPA is gone (404)
├── trim_versions.py ← retention policy for the version list
├── fetch_release_notes.py ← captures each release's real changelog
├── fetch_screenshots.py ← captures App Store screenshots (weekly)
├── build_news.py ← turns changelogs into the in-app news feed
├── sync_legacy_fields.py ← mirrors newest build for older AltStore clients
├── validate_source.py ← publish gate: is this still a valid, safe source?
├── test_ipa_plist.py ← ZIP/plist parser, against real archives
├── test_prune_dead.py ← the safety rails on the script that deletes
├── test_updater_logic.py ← version discovery and merge invariants
├── test_derived_data.py ← README render, legacy mirror, notes, hashes
└── test_validate_source.py ← proves the publish gate actually fires
Stremio uses the same bundle identifier on both iOS and tvOS: com.stremio.pal. Most signing apps do not allow two apps with the same bundleIdentifier inside one source (signing/conflict reasons). That's why:
stremio-ios.json→ iPhone / iPad (com.stremio.palandcom.stremio.ios)stremio-tvos.json→ Apple TV (com.stremio.palandcom.stremio.ios, in separate sources — no conflict)
You can add both to your signing app; the appropriate one shows up per device type.
scan_cdn: Probesdl.strem.io/apple/{semver}b{build}/{ios|tvos}/...URLs in parallel with aThreadPoolExecutor(16 workers). Scans the last known build + buffer range.get_main_app_info_plist: Fetches only the relevant chunks of the IPA via HTTPRangerequests (ZIP EOCD + Central Directory + compressed Info.plist), parses binary or XML plist withplistlib. Typical download: < 5 KB per IPA. The function filters out framework and appex Info.plists, keeping only the main app entry.process_platform: Adds discovered versions to the JSON or refreshes metadata of existing ones. Keeps versions sorted by (version, build) descending.
- Unofficial — Stremio does not support this source. It can change IPA URLs or shut down the CDN at any time.
- Signature expiry — Apps signed with a free Apple ID expire after 7 days, with a paid developer account after 1 year. You'll need to re-sign through your signing app.
- Missing features — Per Stremio's blog, some features (Apple Login, Handoff) don't work in sideloaded builds: "these features cannot be available within sideloadable apps".
- CDN dependency — If Stremio changes its
dl.strem.ioinfrastructure, this repo breaks. Runupdater.py --dry-runperiodically to verify.
Contributions are welcome! See CONTRIBUTING.md.
Especially helpful:
- 🆕 Reporting new versions — open an Issue or PR if the updater missed one
- 🐛 Bug fixes — particularly parse errors and edge cases
- 📚 Documentation — README translations, clarifications, examples
- 🧪 Testing — compatibility with different signing apps
- 🆕 Adding new signing app support — if a signing app has trouble parsing our JSON, file an Issue with the parsing error message
For security issues please see SECURITY.md.
This repository is licensed under the MIT License.
- Stremio is a trademark of SmartCode OOD. This repo is not affiliated with, endorsed by, or sponsored by Stremio or SmartCode OOD.
- AltStore and the source format are defined by AltStore.
- Feather is an open-source project by @claration.
- Original unofficial source inspiration: @blksmr/altstore-stremio.
This source is maintained by the community, with love 🍿