PowerShell utility for migrating CloudStream Android / Android TV Library bookmarks from YFlix to CineStream while preserving Library state, consolidating duplicates, cleaning stale source-provider data, validating the generated backup, and optionally creating a cleanup/tombstone backup.
Tested provider path: YFlix → CineStream
Script:CloudStream-LibraryMigrator.ps1
Version: 1.1.0
PowerShell: Windows PowerShell 5.1 or newer
This is a backup-transformation utility and is not an official CloudStream feature.
CloudStream backup files can contain much more than Library titles. Depending on installed extensions and configuration, a backup may contain cookies, session values, provider settings, repository information, account-related settings, and device/application state.
Do not publish a raw CloudStream backup.
If asking another person or an AI assistant to help adapt this utility:
- Prefer a backup created specifically for testing.
- Remove unrelated settings and credentials when possible.
- Share only the minimum bookmark/cache records needed to understand the extension format.
- Never intentionally publish cookies, tokens, passwords, account identifiers, or private repository credentials.
The public script and examples in this repository contain no user-specific backup filenames, usernames, device names, personal paths, raw Library data, cookies, or account credentials.
The script provides four actions:
| Action | Purpose |
|---|---|
Analyze |
Reads the original backup, finds active YFlix Library records, determines which records can be migrated automatically, and creates NeedsReview.csv only when manual metadata is required. |
Build |
Creates one validated FINAL_CLEANED.txt directly from the untouched original backup. |
Verify |
Compares an original backup with a final backup and checks that the original Library is accounted for. |
Tombstone |
Creates REMOVE_OLD_YFLIX.txt, a minimal backup that neutralizes stale YFlix records that can remain after CloudStream merges a restored backup with existing app data. |
Running the script without -Action displays an interactive menu.
CloudStream Library entries are stored as structured bookmark records inside the backup.
A simplified source bookmark may contain:
Title
Year
Provider
CloudStream bookmark ID
Provider URL
IMDb/TMDb synchronization data
Watch state
Playback state
Poster
Metadata
For the currently supported YFlix → CineStream migration, the important stable identifier is normally the IMDb ID already stored in the bookmark's synchronization metadata.
Conceptually:
Old YFlix bookmark
↓
Read the stored IMDb ID
↓
Check for an existing working bookmark with that IMDb ID
↓
If none exists, construct CineStream's bookmark URL
↓
Calculate the CloudStream bookmark ID
↓
Copy the Library state and compatible auxiliary state
↓
Remove the active YFlix bookmark
↓
Validate the entire generated backup
The script does not normally search IMDb.com. It reads an IMDb identifier that is already present in the CloudStream backup.
If an item has missing or unreliable metadata, the utility puts it in NeedsReview.csv rather than guessing.
A large part of the utility is reusable across CloudStream extensions, but the current release is not a universal provider-to-provider migrator.
These parts are largely provider-independent:
- CloudStream backup parsing
- Library record discovery
- watch-state preservation
- playback/resume-state handling
- IMDb-based duplicate detection
- manual-review CSV handling
- collision protection
- original-vs-final verification
- JSON validation
- generated-file protection
- reporting
- tombstone/neutralization mechanics
The current script explicitly recognizes YFlix as the broken/source provider.
It looks for values such as:
apiName = YFlix
and knows about YFlix-specific cleanup data, including:
YFlix download_header_cache records
YFlix BACKUP_download_header_cache records
Yflix_CURRENT_SERVER
YFlix entries in saved provider preferences
A different source extension may use different provider names and saved keys.
CineStream is currently the implemented destination adapter.
For a movie with a valid IMDb ID, the script constructs a CineStream bookmark URL in this form:
{"id":"tt1234567","type":"movie"}tt1234567 is only a placeholder example.
The target poster pattern implemented by the script is:
https://wsrv.nl/?url=https://images.metahub.space/poster/small/<IMDb_ID>/img
The script then reproduces Java/Kotlin String.hashCode() for the exact provider URL string to generate the corresponding CloudStream bookmark ID.
These rules were verified for the tested CineStream records. Do not assume another extension follows the same rules.
If CineStream stops working, most of the migration engine does not need to be rewritten. The main job is determining how the replacement extension represents a bookmark.
For a new target provider, determine:
-
Provider name
- What value appears in
apiName?
- What value appears in
-
Stable identifier
- Does it use IMDb?
- TMDb?
- MAL/AniList?
- A provider-specific numeric/string ID?
-
Bookmark URL
- What exact string is saved in the CloudStream bookmark's
urlfield?
- What exact string is saved in the CloudStream bookmark's
-
Bookmark ID
- Is the CloudStream
ida Java/Kotlin hash of the saved URL? - Is it supplied directly by the extension?
- Is another formula used?
- Is the CloudStream
-
Poster
- Is a poster URL generated from IMDb/TMDb?
- Does the extension return its own poster URL?
-
Content type
- How are movies and TV series represented?
-
Source cleanup
- What cache/preferences are associated with the broken provider?
- Which keys should be removed or neutralized?
The main target-provider modification points in the script are intentionally marked with comments, including:
New-CineStreamUrl
Get-CineStreamPosterUrlThe source-provider cleanup section is also clearly labeled:
Remove-YFlixCaches
Repair-ProviderPreferences
Apply-YFlixGeneralCleanupThere are additional direct checks for the strings:
YFlix
CineStream
Those should be reviewed when adapting the script.
The easiest approach is usually to create a small controlled sample.
Install the replacement CloudStream extension and manually add a few test titles through that extension.
Using several examples is better than using one because it helps reveal which fields change and which are fixed.
Create a backup after adding those sample records.
Do not publish the complete raw backup.
The useful records are generally the new bookmark entries and closely related state/cache data.
Remove unrelated account/session/provider data before sharing the sample publicly.
Look for:
apiName
url
id
posterUrl
type
syncData
IMDb/TMDb IDs
download_header_cache
watch-state keys
The goal is to understand the transformation:
Stable content identity
↓
Replacement extension's URL/ID format
↓
Valid CloudStream bookmark
Once the pattern is understood, replace or add target-provider helper functions and update the provider-specific checks.
Then run the same Analyze → Build → Verify workflow against a test backup before using it on a real Library.
An AI coding assistant can be useful for adapting the provider-specific pieces, but give it sanitized data.
A useful request would be similar to:
I have a PowerShell CloudStream backup migrator. It currently targets CineStream. Here are sanitized bookmark records from several titles added through another extension. Compare the records, determine how the new extension constructs
apiName,url,id,posterUrl,type, and sync identifiers, then explain what functions/checks in the migrator need to change. Do not modify the backup data itself until the format is verified.
Provide:
- the current public script;
- several sanitized target-extension bookmark examples;
- optionally equivalent source bookmarks for the same titles;
- no cookies, account data, tokens, private repository credentials, or unrelated backup settings.
The AI should first explain the inferred provider format and confidence level. Only then should it generate an adapter or modified script.
A single bookmark can make an accidental relationship look like a rule.
For example, another extension might use:
IMDb ID
TMDb ID
its own internal website ID
a slug
an encoded JSON object
Multiple sample records make it easier to determine which identifier actually controls the provider URL and CloudStream ID.
Example conceptual format:
{"id":"<IMDb_ID>","type":"movie"}If the provider directly accepts IMDb IDs, adaptation may only require changing the provider URL/poster builders and provider name.
If the backup contains IMDb IDs but the destination extension requires TMDb IDs, the migration needs a reliable IMDb → TMDb mapping step.
That can still be automated, but it requires a metadata lookup/source rather than only local backup data.
Some extensions may save URLs such as:
https://provider.example/watch/provider-specific-id
If that provider-specific ID cannot be derived from IMDb/TMDb, the migration tool must either:
- search the destination provider;
- use an extension/provider API;
- import a prebuilt mapping;
- or require manual review.
In that case the generic backup engine is still useful, but discovery of the destination record becomes a separate component.
Place the script and an untouched CloudStream backup in a working folder.
Example:
C:\CloudStreamMigration\
├── CloudStream-LibraryMigrator.ps1
└── original-backup.txt
Open PowerShell in that folder.
If PowerShell blocks script execution for the current session:
Set-ExecutionPolicy -Scope Process BypassThis setting applies only to the current PowerShell process.
.\CloudStream-LibraryMigrator.ps1 `
-Action Analyze `
-OriginalBackup ".\original-backup.txt"Typical information reported:
Active Library records
YFlix records
Ready to migrate
Existing provider matches
Needs manual review
Provider counts
If manual input is necessary, the script creates:
CloudStreamMigration\NeedsReview.csv
Analyze does not modify the source backup.
Possible columns include:
Name
Year
OldId
OldType
Reason
CurrentImdbId
ManualImdbId
TargetType
CorrectedName
CorrectedYear
Enter a verified IMDb title ID, including the tt prefix:
tt1234567
The value above is a placeholder example.
Valid values:
movie
tv
Optional corrected bookmark name.
Example:
Example Movie
Optional corrected four-digit year.
Example:
2020
Do not edit OldId. It identifies the original bookmark record.
After completing NeedsReview.csv when required:
.\CloudStream-LibraryMigrator.ps1 `
-Action Build `
-OriginalBackup ".\original-backup.txt"If this file exists:
CloudStreamMigration\NeedsReview.csv
the script automatically uses it.
A successful build creates:
CloudStreamMigration\FINAL_CLEANED.txt
CloudStreamMigration\MigrationSummary.txt
The original backup remains unchanged.
Before creating a CineStream bookmark, the script checks for an existing non-YFlix bookmark with the same IMDb ID.
If one exists, the utility can retain the existing working bookmark rather than creating a duplicate.
This means an already-working copy from another extension may remain the final destination.
The existing destination's watch state is preserved, and compatible auxiliary state from the YFlix record is only used where appropriate.
Before FINAL_CLEANED.txt is written, the utility checks that:
- no active YFlix Library bookmarks remain;
- no active Library URL/poster still points to YFlix;
- every active bookmark has a watch-state key;
- no duplicate IMDb groups remain;
- CineStream URL/hash IDs are consistent;
- every original Library record maps to a final destination;
- every final Library record is traceable to the original;
- YFlix cache records are removed;
- the YFlix server preference is removed;
- the output is valid JSON.
If validation fails:
VALIDATION FAILED
FINAL_CLEANED.txt was NOT written.
Do not restore a failed/partial result.
To independently compare the source and final backups:
.\CloudStream-LibraryMigrator.ps1 `
-Action Verify `
-OriginalBackup ".\original-backup.txt" `
-FinalBackup ".\CloudStreamMigration\FINAL_CLEANED.txt"Verification attempts to match records using:
- the same CloudStream ID;
- a supplied manual IMDb correction;
- IMDb ID;
- normalized exact title + year as a conservative fallback.
A clean result reports:
RESULT: PASS
Every original Library record is accounted for.
CloudStream restore can merge restored values with keys already stored on the device. A generated backup may contain no active YFlix bookmarks while old YFlix records still survive locally.
Generate a cleanup/tombstone backup from the original source backup:
.\CloudStream-LibraryMigrator.ps1 `
-Action Tombstone `
-OriginalBackup ".\original-backup.txt"Output:
CloudStreamMigration\REMOVE_OLD_YFLIX.txt
For each old YFlix bookmark the cleanup backup writes:
0/result_watch_state/<oldId> = 5
0/result_watch_state_data/<oldId> = "null"
In the currently implemented CloudStream watch-state mapping, 5 represents None.
The cleanup file also neutralizes YFlix cache records and directly associated resume state where present.
- Restore
FINAL_CLEANED.txt. - If stale YFlix cards remain, restore
REMOVE_OLD_YFLIX.txtover the existing installation. - Do not clear application data unless you intentionally want to reset CloudStream.
- If only old images remain, force-stop CloudStream and clear the application cache.
- Reopen CloudStream.
Run:
.\CloudStream-LibraryMigrator.ps1Menu:
CloudStream Library Migration Utility
=====================================================
1. Analyze original backup
2. Build final migrated backup
3. Verify original vs final
4. Generate YFlix cleanup/tombstone backup
5. Exit
-OutputDir ".\Output"-DetailedReportDepending on the selected action, optional files can include:
Analysis.csv
MigrationAudit.csv
VerificationAudit.csv
-OverwriteThe script otherwise protects existing output files from accidental replacement.
CloudStreamMigration\
├── NeedsReview.csv
├── FINAL_CLEANED.txt
├── MigrationSummary.txt
└── REMOVE_OLD_YFLIX.txt
Optional detailed reports are only generated with -DetailedReport.
1. Create a fresh CloudStream backup.
2. Preserve an untouched copy.
3. Run Analyze.
4. Complete NeedsReview.csv if generated.
5. Run Build.
6. Review MigrationSummary.txt.
7. Run Verify.
8. Restore FINAL_CLEANED.txt on a test/device installation.
9. Test several migrated Library entries.
10. Use the Tombstone action only if stale source-provider entries remain.
11. Keep the original backup as the rollback point.
| ID | State |
|---|---|
0 |
Watching |
1 |
Completed |
2 |
On Hold |
3 |
Dropped |
4 |
Plan to Watch |
5 |
None |
These values are used for Library-state preservation and tombstone cleanup.
For the current PowerShell process:
Set-ExecutionPolicy -Scope Process BypassOpen:
CloudStreamMigration\NeedsReview.csv
Complete the required metadata, save the file, and rerun Build.
Move/rename the existing output, or intentionally use:
-OverwriteThe script validates the Java/Kotlin hash implementation with a provider-neutral test string:
cloudstream-migrator-self-test
→ -1527676709
Do not bypass this validation. A bad hash implementation can produce invalid destination bookmark IDs.
Generate and restore the Tombstone backup. This addresses stale local records that were not deleted by CloudStream's merge-style restore.
This release has been tested for:
YFlix → CineStream
It should not be presented as supporting arbitrary CloudStream extensions without modification and testing.
Other extensions may use:
- different bookmark URL structures;
- TMDb instead of IMDb;
- provider-specific IDs;
- different poster sources;
- different type representations;
- non-hash bookmark IDs;
- provider-specific TV episode identifiers;
- additional cache/preference keys.
Movies with stable IMDb IDs are the simplest migration case. TV-series migrations can be more complex because episode identifiers and playback state may be provider-specific.
After a successful migration, keep:
original-backup.txt
CloudStream-LibraryMigrator.ps1
NeedsReview.csv
FINAL_CLEANED.txt
MigrationSummary.txt
REMOVE_OLD_YFLIX.txt
README.md
Keep the untouched original backup as the rollback source.
Provider formats and CloudStream internals can change. Always analyze and verify a fresh backup before restoring generated data.
If adapting this utility to another extension, verify the new provider format from multiple sanitized sample records before modifying a real Library.