Skip to content

Ap0dexMe0/NF-MSL

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Netflix MSL Universal Handshake

A cross-platform MSL (Message Security Layer) authentication toolkit for Netflix. Implements a unified handshake layer that works across Android, iOS, Smart TV, Web, and MGK all driven from a single entry point with shared credential management.


Table of Contents


Requirements

pip install -r requirements.txt

Key dependencies: pywidevine, pycryptodome, requests, coloredlogs, certifi, jsonpickle.


Configuration

Edit config.ini before running:

[NETFLIX]
EMAIL    = your@email.com
PASSWORD = yourpassword

Credentials are read once at startup. They are never accepted as command-line arguments.


Project Structure

NF-MSL/
├── main.py                      # CLI entry point
├── config.ini                   # Netflix credentials
├── devices/                     # WVD device files (gitignored)
├── output/                      # Per-platform output (gitignored)
└── modules/
    ├── config.py                # Config loader
    ├── logging.py               # Coloredlogs setup
    ├── session.py               # requests.Session factory (TLS + proxy)
    ├── helpers.py               # Shared utilities
    ├── msl/                     # MSL protocol layer
    │   ├── base.py              # MSLBase, MSLKeys, send_message
    │   ├── android.py           # MSL_ANDROID (Widevine + RSA)
    │   ├── ios.py               # MSL_IOS
    │   ├── tv.py                # MSL_TV
    │   ├── web.py               # MSL_WEB (RSA)
    │   └── mgk.py               # MSL_MGK (AUTHENTICATED_DH)
    └── platforms/               # Per-platform login orchestration
        ├── android_rsa.py       # run_android_rsa
        ├── android.py           # run_android
        ├── ios.py               # run_ios
        ├── tv.py                # run_tv
        ├── tv_otp.py            # run_tv_otp
        ├── web.py               # run_web
        └── mgk.py               # run_mgk

Platforms

Android RSA (no WVD)

Emulates a Samsung Galaxy Z Flip3 (SM-F711N) running Android 15. Uses an RSA/ASYMMETRIC_WRAPPED key exchange — no Widevine device file required.

MSL flow:

  1. Bootstrap HTTP session → nfvdid cookie via appboot
  2. RSA key exchange (MSL handshake) using NFCDCH-02-* ESN
  3. CLCSScreenUpdate GraphQL — submit email + password via MSL
  4. Load /browse to finalize session

Output: android/netflix_auth_cookies_rsa.json, netflix_auth_tokens_rsa.json


Android

Emulates a Samsung Galaxy Z Flip3 (SM-F711N) running Android 15 with full Widevine L3 authentication.

MSL flow:

  1. Bootstrap HTTP session → nfvdid via appboot
  2. Widevine key exchange using the provided .wvd
  3. Load login page → CLCSScreenUpdate (CLCS web login) to obtain NetflixId/SecureNetflixId cookies
  4. VerifyLoginMslRequest (samurai) — binds the MSL session to the authenticated account
  5. Decrypt response header → extract useridtoken

If VerifyLoginMslRequest returns incorrect_password, the CLCS login fallback is triggered automatically and the request is retried with the fresh auth cookies.

Output (per WVD system ID): android/netflix_auth_tokens_{sid}.json, netflix_auth_useridtoken_{sid}.json, netflix_auth_cookies_{sid}.json


iOS

Emulates an iPhone 15 Pro Max running iOS 18.

MSL flow:

  1. Bootstrap HTTP session → nfvdid via appboot
  2. Widevine key exchange using the provided .wvd
  3. MembershipStatus GraphQL probe (anonymous)
  4. Load login page → extract clcsSessionId + renditionId
  5. CLCSScreenUpdate — submit email + password via MSL to ios.prod.cloud.netflix.com/graphql

Output (per WVD system ID): ios/netflix_auth_cookies_{sid}.json


TV (email/password)

Emulates an NVIDIA SHIELD Android TV (2019).

MSL flow:

  1. Obtain nfvdid from the Android TV config endpoint
  2. Bootstrap AUI + pre-login pathEvaluator
  3. Widevine key exchange using the provided .wvdmintCookies
  4. CLCS session initiation (clcsLegacyMoneyballInitiateSession)
  5. Multi-step credential flow:
    • Welcome landing → web sign-in → email → password
    • Submit credentials via clcsScreenUpdate
  6. Post-login PBO config + token refresh (getPartnerToken, ping)
  7. Save cookies including NetflixId, SecureNetflixId, gsid

Output (per WVD system ID): tv/netflix_cookies_{sid}.json, useridtoken_{sid}.json, msl_debug_trace_{sid}.json, password_login_response_{sid}.json


TV OTP (pairing code)

Same device profile as TV, but authenticates via a one-time pairing code instead of email/password.

MSL flow: 1–3. Same as TV up through mintCookies 4. CLCS session initiation 5. Navigate to webSignIn mode → extract an 8-digit TV code 6. Display the code and poll https://www.netflix.com/tv2 every 5 seconds until the user activates it 7. Send continueAction to complete sign-in

Interactive: visit https://www.netflix.com/tv2 in a browser and enter the displayed code to proceed.

Output (per WVD system ID): tv_otp/netflix_cookies_{sid}.json, useridtoken_{sid}.json


Web

Emulates Chrome 146 on Windows 10.

MSL flow:

  1. Bootstrap anonymous browser session (netflix.com/login)
  2. MembershipStatus GraphQL probe
  3. Extract clcsSessionId + renditionId from login page HTML
  4. CLCSScreenUpdate — submit email + password to PASSWORD_LOGIN
  5. Optional CLCSSendFeedback if the server returns a feedback payload
  6. Load /browse to finalize session
  7. CLCSInterstitialProfileGate probe
  8. ALE provision via MSL RSA handshake

Output: browser/netflix_auth_cookies.json


MGK (Model Group Key)

Uses the MGK / AUTHENTICATED_DH MSL key-exchange scheme, authenticating with a pre-provisioned KpeKph key pair rather than a Widevine device.

Requires two sidecar files:

File Content
KpeKph Base64 AES-128 encryption key + Base64 HMAC-SHA256 key, comma-separated
ESNID Model-group identity string (the MGK sender ESN)

Files are auto-discovered in the working directory, any subdirectory, or via environment variables:

export MSL_KPEKPH_PATH=/path/to/KpeKph

Or pass --kpekph and --esnid on the command line.

MSL flow:

  1. Load KpeKph → derive wrapping key
  2. Generate DH keypair → build AUTHENTICATED_DH key-request (mechanism=MGK)
  3. Handshake → derive session encryption + HMAC keys from shared secret
  4. Send EMAIL_PASSWORD user-auth message → receive useridtoken

Output: mgk/netflix_auth_cookies_mgk.json


Usage

# Android RSA (no WVD needed)
python main.py --platform android_rsa

# Android with a single WVD
python main.py --platform android --wvd devices/my_device_l3.wvd

# iOS
python main.py --platform ios --wvd devices/my_device_l3.wvd

# TV (email/password)
python main.py --platform tv --wvd devices/my_device.wvd

# TV OTP (pairing code — interactive)
python main.py --platform tv_otp --wvd devices/my_device.wvd

# Web (Chrome emulation)
python main.py --platform web

# MGK
python main.py --platform mgk --esnid path/to/ESNID --kpekph path/to/KpeKph

# Force fresh MSL handshake (ignore cached keys)
python main.py --platform tv --wvd devices/my_device.wvd --new-msl

# Skip TLS verification
python main.py --platform web --no-verify

# Use a proxy
python main.py --platform tv --wvd devices/my_device.wvd --proxy http://127.0.0.1:8080
python main.py --platform tv --wvd devices/my_device.wvd --proxy http://user:pass@proxy.example.com:3128

Flags

Flag Applies to Description
--platform all Required. One of android_rsa, android, ios, tv, tv_otp, web, mgk
--wvd android, ios, tv, tv_otp Path or glob to .wvd file(s). Required for these platforms
--kpekph mgk Path to KpeKph key file (auto-discovered if omitted)
--esnid mgk ESN identity string or file path. Required for mgk
--new-msl all Force a fresh MSL handshake, ignoring cached keys
--no-verify all Disable TLS certificate verification
--proxy all Proxy URL — http://ip:port or http://user:pass@ip:port

WVD Glob Testing

Pass a glob pattern to --wvd to test multiple .wvd files in sequence. Only .wvd files are matched.

python main.py --platform android --wvd "devices/*.wvd"
python main.py --platform tv      --wvd "devices/*"

The tool loops through all matching files sorted by name, waits 10 seconds between each to avoid throttling, and prints a pass/fail summary at the end:

MSL HANDSHAKE - INFO - Found 14 .wvd file(s) to test
MSL HANDSHAKE - INFO - --- [1/14] WVD: changhong_androidtv_22594_l3.wvd ---
...
MSL HANDSHAKE - INFO - === Results: 3/14 passed ===
MSL HANDSHAKE - INFO -   PASS: changhong_androidtv_22594_l3.wvd
MSL HANDSHAKE - WARNING -   FAIL: amlogic_mbox_22594_l3.wvd

Output files include the WVD's Widevine system ID, so runs never overwrite each other:

output/tv/netflix_cookies_22594.json
output/tv/useridtoken_22594.json

Proxy Support

All platforms support an HTTP/HTTPS proxy. The proxy is applied at both the session level (all HTTP requests) and explicitly on every MSL send_message call.

# IP:port
python main.py --platform tv --wvd devices/device.wvd --proxy http://192.168.1.1:8080

# Authenticated
python main.py --platform tv --wvd devices/device.wvd --proxy http://user:pass@proxy.host:3128

Output Files

All output is written under the output/ directory, organised by platform. Files that depend on a WVD include the Widevine system ID in their name so multiple WVDs can be tested without overwriting results.

Platform Output files
android_rsa android/netflix_auth_cookies_rsa.json, netflix_auth_tokens_rsa.json, netflix_auth_useridtoken_rsa.json
android android/netflix_auth_cookies_{sid}.json, netflix_auth_tokens_{sid}.json, netflix_auth_useridtoken_{sid}.json
ios ios/netflix_auth_cookies_{sid}.json
tv tv/netflix_cookies_{sid}.json, useridtoken_{sid}.json, msl_debug_trace_{sid}.json, password_login_response_{sid}.json
tv_otp tv_otp/netflix_cookies_{sid}.json, useridtoken_{sid}.json
web browser/netflix_auth_cookies.json
mgk mgk/netflix_auth_cookies_mgk.json

MSL key caches are also stored per platform (and per WVD system ID where applicable) and reused across runs. They expire automatically when the master token has fewer than 10 hours remaining.


Big thanks to Hugoved

  • for the foundational work on MSL (Message Security Layer) reverse engineering and the original pywidevine implementation that made this unified handshake toolkit possible.

About

Netflix MSL Handshake for All Platforms

Topics

Resources

Stars

20 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages