Android library for YouTube cipher deobfuscation and PoToken generation.
The WebView signature-cipher / n-transform deciphering here (CipherDeobfuscator, CipherWebView,
the injected window._cipherSigFunc) was originally written by me
(alltechdev) — first implemented into zemer-app on
2026-02-12
(f905d49),
then added to Metrolist two days later on 2026-02-14
(0750a63d)
This repository is that same code, extracted into a standalone Android library
(com.zemer:cipher).
Remote config: zemer-app, Metrolist, and Echo-Music fetch player_configs.json from this repo's master
at runtime (via PlayerConfigStore) to self-heal YouTube player rotations without an app update.
Code reuse: the deciphering code has also been copied into many other projects — these bundle the code only and do not pull config updates from here. Verified examples:
…plus dozens of other forks and derivative apps.
- Signature cipher deobfuscation for YouTube streaming URLs
- N-parameter transformation to avoid throttling
- PoToken generation using BotGuard
- Remote-updatable player configs — a config pushed to this repo's
masterfixes deployed apps within minutes, no APK release needed
YouTube rotates its player_ias JS frequently; each rotation needs a per-player config
(sig call expression, n-transform URL class, signatureTimestamp). All configs live in
one JSON file, which is:
- Bundled in the APK as the offline default,
- Fetched at runtime by
PlayerConfigStorefrom this repo's rawmasterURL (6 h TTL + ETag), and force-refreshed the moment an unknown player breaks deciphering — so pushing a new entry tomasteris the deploy, - Read by the
zemer-apptest harness — app, devices, and tests cannot drift apart.
"445213fb": { "sig": "mP(4,155,INPUT)", "nClass": "Yx", "sts": 20613, "aliases": ["d62bd338"] }- key — the 8-hex player hash from the player JS URL;
aliases— the md5-of-first-10000-bytes fallback hash sig— the signature deobfuscation call, locked toname(int,int,INPUT)nClass— the URL class for the n-transform IIFE (built from a local template)sts— the player's signatureTimestamp
- In
zemer-app:node tests/validate-player-config.mjs <hash>— deciphers a real stream and checks the CDN returns HTTP 206 (the only ground truth; multiple constant pairs can "decipher" while only one is accepted). It prints a paste-ready JSON entry. - Add the entry to
player_configs.jsonhere. Duplicate hashes/aliases reject the whole file — run the unit tests. - Push to
master— deployed apps self-heal from that URL within minutes. - Bump the submodule pointer in
zemer-appafterwards (bundled defaults stay fresh).
PlayerConfigParser is the validation boundary: every value is regex-locked so remote data
can never inject free-form JS into the cipher WebView. Invalid entries are skipped; invalid
files (including hash/alias collisions) are rejected wholesale and devices keep their
last-good table. Bump schemaVersion only on breaking shape changes — older apps reject
newer schema files and keep working from their last-good table.
Run the tests with ./gradlew :library:testDebugUnitTest. The config-parity/ fixtures are
shared with the zemer-app harness: file-level accept/reject verdicts (and the n-IIFE
template) are pinned byte-for-byte across both readers.
// Initialize in your Application class
ZemerCipher.initialize(
context = applicationContext,
proxy = yourProxy, // optional
debugLogging = BuildConfig.DEBUG // optional
)// Deobfuscate a signature cipher URL
val deobfuscatedUrl = CipherDeobfuscator.deobfuscateStreamUrl(signatureCipher, videoId)
// Transform n-parameter in URL
val transformedUrl = CipherDeobfuscator.transformNParamInUrl(url)val generator = PoTokenGenerator()
val result = generator.getWebClientPoToken(videoId, sessionId)
// result.playerRequestPoToken - for player requests
// result.streamingDataPoToken - for streaming data requests- PoToken generation patterns based on BgUtils (MIT License)
- Cipher function extraction uses standard YouTube deobfuscation techniques (as documented by yt-dlp, NewPipe, etc.)
All other code (WebView implementation, runtime execution, n-parameter transform logic) is custom implementation.
GPL-3.0