Every YouTube streaming URL includes anDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ZemerTeam/zemer-cipher/llms.txt
Use this file to discover all available pages before exploring further.
n= query parameter. If a request reaches the CDN with an untransformed n value, the CDN recognizes that the player’s transform function was never run and intentionally caps delivery to roughly 50 KB/s — or returns a 403 entirely. Zemer Cipher prevents this by running the actual player JavaScript to transform the n value before the stream request is made.
The n-Parameter
Then value is a short, random-looking alphanumeric string embedded in the CDN URL. The player JavaScript contains an obfuscated single-argument function that accepts the raw n value and returns the accepted transformed value. The CDN validates the transformation server-side: if the value it receives does not match what the function would have produced, bandwidth is throttled regardless of connection speed.
Without the transform, sustained playback at any quality above the lowest tier is effectively impossible.
How N-Transform Works
1. Identify the n-transform functionFunctionNameExtractor.extractNFunctionInfo() resolves the function to use:
- The player hash is looked up in
PlayerConfigStore. If a config entry is found, thenClassfield (e.g.Yx) is used to build the transform IIFE locally viaPlayerConfigParser.buildNJsExpression():
- If no config entry exists, legacy regex patterns scan the player JS to extract the function name and optional array index.
window._nTransformFunc
The resolved expression is injected into the player JS as an export inside the IIFE closure, just before })(_yt_player);:
CipherWebView used for signature deobfuscation. Both transforms share the single WebView instance.
3. Transform the URL
CipherDeobfuscator.transformNParamInUrl(url) extracts the n= value from the URL, calls webView.transformN(nValue) which dispatches a transformN(...) call via WebView.evaluateJavascript, waits for the CipherBridge.onNResult callback, and replaces the original n= value in the URL with the transformed value:
Brute-Force Fallback
Whenwindow._nTransformFunc is not exported — because no config entry matched and regex extraction also failed — the discoverAndInit() JavaScript that runs at WebView load time performs a brute-force scan:
- It iterates over all property names on
windowusingObject.getOwnPropertyNames(window). - For each property that is a function with exactly one argument, it calls the function with the test input
"T2Xw3pWQ_Wk0xbOg". - If the result is a string that differs from the input, has at least 5 characters, and matches
/^[a-zA-Z0-9_-]+$/, it is treated as the n-transform function. - The first passing candidate is assigned to
window._nTransformFuncand its name is reported back viaCipherBridge.onDiscoveryDone.
webkit*, on* event handlers), the CipherBridge interface itself, and previously set export slots are skipped to avoid false positives.
N-Class Regex Validation
nClass values from remote player configs are validated in PlayerConfigParser against:
nClass to a bare JavaScript identifier — no operators, no brackets, no dots. The n-transform IIFE template is defined entirely in PlayerConfigParser.buildNJsExpression() in the library source. The remote config supplies only the identifier; the actual executable expression is always constructed locally from that fixed template.